Author: shawkins
Date: 2011-08-03 11:13:06 -0400 (Wed, 03 Aug 2011)
New Revision: 3357
Modified:
branches/7.4.x/build/kits/jboss-container/teiid-releasenotes.html
branches/7.4.x/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPExecutionFactory.java
branches/7.4.x/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPSyncQueryExecution.java
branches/7.4.x/documentation/reference/src/main/docbook/en-US/content/translators.xml
Log:
TEIID-1659 adding pagination support for ldap
Modified: branches/7.4.x/build/kits/jboss-container/teiid-releasenotes.html
===================================================================
--- branches/7.4.x/build/kits/jboss-container/teiid-releasenotes.html 2011-08-01 18:58:02
UTC (rev 3356)
+++ branches/7.4.x/build/kits/jboss-container/teiid-releasenotes.html 2011-08-03 15:13:06
UTC (rev 3357)
@@ -69,6 +69,7 @@
<LI><B>Sync at Start</B> - When a node is restarted in a cluster, at
end of start cycle Teiid will asynchronously fetch the cached internal materialized view
contents from other nodes.
</UL>
</LI>
+ <LI><B>LDAP Pagination</B> - the ldap translator now supports
pagination for retrieving large results from directory servers like Active Directory and
OpenLDAP.
</UL>
<h2><a name="Compatibility">Compatibility
Issues</a></h2>
Modified:
branches/7.4.x/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPExecutionFactory.java
===================================================================
---
branches/7.4.x/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPExecutionFactory.java 2011-08-01
18:58:02 UTC (rev 3356)
+++
branches/7.4.x/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPExecutionFactory.java 2011-08-03
15:13:06 UTC (rev 3357)
@@ -53,6 +53,7 @@
private String searchDefaultBaseDN;
private boolean restrictToObjectClass;
private SearchDefaultScope searchDefaultScope = SearchDefaultScope.ONELEVEL_SCOPE;
+ private boolean usePagination;
public LDAPExecutionFactory() {
this.setMaxInCriteriaSize(1000);
@@ -89,7 +90,7 @@
@Override
public ResultSetExecution createResultSetExecution(QueryExpression
command,ExecutionContext executionContext, RuntimeMetadata metadata, LdapContext context)
throws TranslatorException {
- return new LDAPSyncQueryExecution((Select)command, this, context);
+ return new LDAPSyncQueryExecution((Select)command, this, executionContext, context);
}
@Override
@@ -142,5 +143,15 @@
@Override
public boolean supportsNotCriteria() {
return true;
+ }
+
+ @TranslatorProperty(display="Use Pagination", description="Use a
PagedResultsControl to page through large results. This is not supported by all directory
servers.")
+ public boolean usePagination() {
+ return usePagination;
}
+
+ public void setUsePagination(boolean usePagination) {
+ this.usePagination = usePagination;
+ }
+
}
Modified:
branches/7.4.x/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPSyncQueryExecution.java
===================================================================
---
branches/7.4.x/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPSyncQueryExecution.java 2011-08-01
18:58:02 UTC (rev 3356)
+++
branches/7.4.x/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPSyncQueryExecution.java 2011-08-03
15:13:06 UTC (rev 3357)
@@ -91,6 +91,8 @@
import javax.naming.directory.SearchResult;
import javax.naming.ldap.Control;
import javax.naming.ldap.LdapContext;
+import javax.naming.ldap.PagedResultsControl;
+import javax.naming.ldap.PagedResultsResponseControl;
import javax.naming.ldap.SortControl;
import javax.naming.ldap.SortKey;
@@ -98,6 +100,7 @@
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
import org.teiid.metadata.Column;
+import org.teiid.translator.ExecutionContext;
import org.teiid.translator.ResultSetExecution;
import org.teiid.translator.TranslatorException;
import org.teiid.translator.TypeFacility;
@@ -119,6 +122,8 @@
private IQueryToLdapSearchParser parser;
private Select query;
private LDAPExecutionFactory executionFactory;
+ private ExecutionContext executionContext;
+ private SearchControls ctrls;
/**
* Constructor
@@ -127,10 +132,11 @@
* @param logger the ConnectorLogger
* @param ldapCtx the LDAP Context
*/
- public LDAPSyncQueryExecution(Select query, LDAPExecutionFactory factory, LdapContext
ldapCtx) {
+ public LDAPSyncQueryExecution(Select query, LDAPExecutionFactory factory,
ExecutionContext context, LdapContext ldapCtx) {
this.ldapConnection = ldapCtx;
this.query = query;
this.executionFactory = factory;
+ this.executionContext = context;
}
/**
@@ -146,31 +152,40 @@
// Create and configure the new search context.
createSearchContext();
- SearchControls ctrls = setSearchControls();
- setStandardRequestControls();
+ ctrls = setSearchControls();
+ String ctxName = searchDetails.getContextName();
+ String filter = searchDetails.getContextFilter();
+ if (ctxName == null || filter == null || ctrls == null) {
+ throw new TranslatorException(LogConstants.CTX_CONNECTOR, "Search context,
filter, or controls were null. Cannot execute search."); //$NON-NLS-1$
+ }
+ setRequestControls(null);
// Execute the search.
- executeSearch(ctrls);
+ executeSearch();
}
/**
* Set the standard request controls
*/
- private void setStandardRequestControls() throws TranslatorException {
- Control[] sortCtrl = new Control[1];
+ private void setRequestControls(byte[] cookie) throws TranslatorException {
+ List<Control> ctrl = new ArrayList<Control>();
SortKey[] keys = searchDetails.getSortKeys();
- if (keys != null) {
- try {
- sortCtrl[0] = new SortControl(keys, Control.NONCRITICAL);
- this.ldapCtx.setRequestControls(sortCtrl);
- LogManager.logTrace(LogConstants.CTX_CONNECTOR, "Sort ordering was requested,
and sort control was created successfully."); //$NON-NLS-1$
- } catch (NamingException ne) {
- final String msg =
LDAPPlugin.Util.getString("LDAPSyncQueryExecution.setControlsError") +
//$NON-NLS-1$
- " : "+ne.getExplanation(); //$NON-NLS-1$
- throw new TranslatorException(msg);
- } catch(IOException e) {
- final String msg =
LDAPPlugin.Util.getString("LDAPSyncQueryExecution.setControlsError");
//$NON-NLS-1$
- throw new TranslatorException(e,msg);
+ try {
+ if (keys != null) {
+ ctrl.add(new SortControl(keys, Control.NONCRITICAL));
}
+ if (this.executionFactory.usePagination()) {
+ ctrl.add(new PagedResultsControl(this.executionContext.getBatchSize(), cookie,
Control.CRITICAL));
+ }
+ if (!ctrl.isEmpty()) {
+ this.ldapCtx.setRequestControls(ctrl.toArray(new Control[ctrl.size()]));
+ LogManager.logTrace(LogConstants.CTX_CONNECTOR, "Sort/pagination controls were
created successfully."); //$NON-NLS-1$
+ }
+ } catch (NamingException ne) {
+ final String msg =
LDAPPlugin.Util.getString("LDAPSyncQueryExecution.setControlsError") +
//$NON-NLS-1$
+ " : "+ne.getExplanation(); //$NON-NLS-1$
+ throw new TranslatorException(ne, msg);
+ } catch(IOException e) {
+ throw new TranslatorException(e);
}
}
@@ -219,22 +234,14 @@
* Perform the LDAP search against the subcontext, using the filter and
* search controls appropriate to the query and model metadata.
*/
- private void executeSearch(SearchControls ctrls) throws TranslatorException {
- String ctxName = searchDetails.getContextName();
+ private void executeSearch() throws TranslatorException {
String filter = searchDetails.getContextFilter();
- if (ctxName == null || filter == null || ctrls == null) {
- LogManager.logError(LogConstants.CTX_CONNECTOR, "Search context, filter, or
controls were null. Cannot execute search."); //$NON-NLS-1$
- }
try {
searchEnumeration = this.ldapCtx.search("", filter, ctrls); //$NON-NLS-1$
} catch (NamingException ne) {
- LogManager.logError(LogConstants.CTX_CONNECTOR, "LDAP search failed. Attempted to
search context " //$NON-NLS-1$
- + ctxName + " using filter " + filter); //$NON-NLS-1$
final String msg =
LDAPPlugin.Util.getString("LDAPSyncQueryExecution.execSearchError");
//$NON-NLS-1$
- throw new TranslatorException(msg + " : " + ne.getExplanation());
//$NON-NLS-1$
+ throw new TranslatorException(ne, msg + " : " + ne.getExplanation());
//$NON-NLS-1$
} catch(Exception e) {
- LogManager.logError(LogConstants.CTX_CONNECTOR, "LDAP search failed. Attempted to
search context " //$NON-NLS-1$
- + ctxName + " using filter " + filter); //$NON-NLS-1$
final String msg =
LDAPPlugin.Util.getString("LDAPSyncQueryExecution.execSearchError");
//$NON-NLS-1$
throw new TranslatorException(e, msg);
}
@@ -294,6 +301,27 @@
SearchResult searchResult = (SearchResult) searchEnumeration.next();
result = getRow(searchResult);
}
+
+ if (result == null && this.executionFactory.usePagination()) {
+ byte[] cookie = null;
+ Control[] controls = ldapCtx.getResponseControls();
+ if (controls != null) {
+ for (int i = 0; i < controls.length; i++) {
+ if (controls[i] instanceof PagedResultsResponseControl) {
+ PagedResultsResponseControl prrc =
(PagedResultsResponseControl)controls[i];
+ cookie = prrc.getCookie();
+ }
+ }
+ }
+
+ if (cookie == null) {
+ return null;
+ }
+
+ setRequestControls(cookie);
+ executeSearch();
+ return next();
+ }
return result;
} catch (SizeLimitExceededException e) {
@@ -451,22 +479,4 @@
}
}
-
- /**
- * Active Directory and OpenLDAP supports PagedResultsControls, so I left
- * this method in here in case we decide to extend support for this control
- * in the future.
- */
-// private void setADRequestControls(int maxBatchSize) {
-// try {
-// ldapCtx.setRequestControls(new Control[] { new PagedResultsControl(
-// maxBatchSize, Control.CRITICAL) });
-// } catch (NamingException ne) {
-// logger.logError("Failed to set page size for LDAP results. Please ensure that
paged results controls are supported by the LDAP server implementation.");
//$NON-NLS-1$
-// ne.printStackTrace();
-// } catch (IOException ioe) {
-// logger.logError("IO Exception while setting paged results control.");
//$NON-NLS-1$
-// ioe.printStackTrace();
-// }
-// }
}
Modified:
branches/7.4.x/documentation/reference/src/main/docbook/en-US/content/translators.xml
===================================================================
---
branches/7.4.x/documentation/reference/src/main/docbook/en-US/content/translators.xml 2011-08-01
18:58:02 UTC (rev 3356)
+++
branches/7.4.x/documentation/reference/src/main/docbook/en-US/content/translators.xml 2011-08-03
15:13:06 UTC (rev 3357)
@@ -545,6 +545,11 @@
<entry>Restrict Searches to objectClass named in the Name
field for a table</entry>
<entry>false</entry>
</row>
+ <row>
+ <entry>UsePagination</entry>
+ <entry>Use a PagedResultsControl to page through large
results. This is not supported by all directory servers.</entry>
+ <entry>false</entry>
+ </row>
</tbody>
</tgroup>
</table>