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
51
52
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
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 }