View Javadoc

1   package com.atlassian.user.impl.ldap.search.page;
2   
3   import com.atlassian.user.EntityException;
4   import com.atlassian.user.impl.ldap.repository.LdapContextFactory;
5   import com.atlassian.user.impl.ldap.search.LDAPPagerInfo;
6   import com.atlassian.user.search.page.AbstractPrefetchingPager;
7   import com.atlassian.user.util.EnumerationAdaptor;
8   import com.atlassian.user.util.LDAPUtils;
9   import com.atlassian.util.profiling.UtilTimerStack;
10  import net.sf.ldaptemplate.support.filter.Filter;
11  import org.apache.log4j.Logger;
12  
13  import javax.naming.NamingEnumeration;
14  import javax.naming.NamingException;
15  import javax.naming.directory.DirContext;
16  import javax.naming.directory.SearchControls;
17  import javax.naming.directory.SearchResult;
18  import java.util.Iterator;
19  import java.util.List;
20  
21  public abstract class AbstractLDAPPager<T> extends AbstractPrefetchingPager<T> implements Iterator<T>
22  {
23      protected final Logger log = Logger.getLogger(this.getClass());
24      protected NamingEnumeration<SearchResult> enume;
25      protected Filter originalQuery;
26      protected LdapContextFactory repository;
27      protected String originalBaseSearchContext;
28      protected boolean searchAllDepths;
29      protected String[] returningAttributes;
30      private int timeLimitMillis;
31      public boolean closed;
32  
33      protected AbstractLDAPPager(LdapContextFactory repository, LDAPPagerInfo info)
34      {
35          this.repository = repository;
36          this.enume = info.getNamingEnumeration();
37          this.originalQuery = info.getLDAPQuery();
38          this.originalBaseSearchContext = info.getBaseSearchContext();
39          this.searchAllDepths = info.isSearchAllDepths();
40          this.returningAttributes = info.getReturningAttributes();
41          this.timeLimitMillis = info.getTimeToLive();
42      }
43  
44      public AbstractLDAPPager()
45      {
46  
47      }
48  
49      /**
50       * Parses the {@link SearchResult} and stores the result in the list of prefetched items.
51       *
52       * @return the {@link List} of prefetched results.
53       */
54      protected abstract List<T> preloadSearchResult(SearchResult result, List<T> prefetched) throws EntityException;
55  
56      public void remove()
57      {
58          throw new UnsupportedOperationException("This iterator does not support removal.");
59      }
60  
61      /**
62       * Preloads the page into the prefetched list.
63       */
64      protected void preload()
65      {
66          indexOfFirstItemInCurrentPage = idx;
67  
68          if (UtilTimerStack.isActive())
69          {
70              UtilTimerStack.push(this.getClass().getName() + "_preload__(originalQuery= " + originalQuery + ")");
71          }
72  
73          DirContext ctx = null;
74  
75          try
76          {
77              if (closed)
78              {
79                  ctx = repository.getLDAPContext();
80                  SearchControls ctls = LDAPUtils.createSearchControls(returningAttributes, searchAllDepths,
81                      timeLimitMillis);
82                  if (log.isDebugEnabled())
83                  {
84                      log.debug("AbstractLDAPPager.preload:" + originalQuery.encode());
85                  }
86                  enume = ctx.search(originalBaseSearchContext, originalQuery.encode(), ctls);
87              }
88  
89              super.preload(new EnumerationAdaptor<SearchResult>(enume));
90          }
91          catch (Exception e)
92          {
93              log.error("Error while paging through results", e);
94              throw new RuntimeException("Unexpected error paging through LDAP results: " + e.getMessage(), e);
95          }
96          finally
97          {
98              if (enume != null)
99              {
100                 try { enume.close(); } catch (NamingException e) { log.error("Error closing enumeration.", e); }
101             }
102 
103             if (ctx != null)
104             {
105                 try { ctx.close(); } catch (NamingException e) { log.error("Error closing context.", e); }
106             }
107 
108             closed = true;
109         }
110 
111         if (UtilTimerStack.isActive())
112         {
113             UtilTimerStack.pop(this.getClass().getName() + "_preload__(originalQuery= " + originalQuery + ")");
114         }
115     }
116 
117     protected List<T> fetch(Object element, List<T> prefetched) throws EntityException
118     {
119         return preloadSearchResult((SearchResult) element, prefetched);
120     }
121 
122 }