// GHH 20080326 - set all batches as last batch after an exception // is thrown calling a method on the enumeration. Per Javadoc for // javax.naming.NamingEnumeration, enumeration is invalid after an // exception is thrown - by setting last batch indicator we prevent // it from being used again. // GHH 20080326 - also added return of explanation for generic // NamingException public List<?> next() throws TranslatorException { try { if (unwrapIterator != null) { if (unwrapIterator.hasNext()) { return unwrapIterator.next(); } unwrapIterator = null; } // The search has been executed, so process up to one batch of // results. List<?> result = null; while (result == null && searchEnumeration != null && searchEnumeration.hasMore()) { SearchResult searchResult = (SearchResult) searchEnumeration.next(); try { result = getRow(searchResult); } catch (InvalidNameException e) { } } 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(); } if (result != null) { resultCount++; } return result; } catch (SizeLimitExceededException e) { if (resultCount != searchDetails.getCountLimit()) { String msg = LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12008); TranslatorException te = new TranslatorException(e, msg); if (executionFactory.isExceptionOnSizeLimitExceeded()) { throw te; } this.executionContext.addWarning(te); LogManager.logWarning(LogConstants.CTX_CONNECTOR, e, msg); } return null; // GHH 20080326 - if size limit exceeded don't try to read more results } catch (NamingException ne) { throw new TranslatorException(ne, LDAPPlugin.Util.gs("ldap_error")); // $NON-NLS-1$ } }
/** Set the standard request controls */ private void setRequestControls(byte[] cookie) throws TranslatorException { List<Control> ctrl = new ArrayList<Control>(); SortKey[] keys = searchDetails.getSortKeys(); 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); } }
/** * method to execute the supplied query * * @param query the query object. * @param maxBatchSize the max batch size. */ @Override public void execute() throws TranslatorException { String ctxName = this.searchDetails.getContextName(); String filter = this.searchDetails.getContextFilter(); if (ctxName == null || filter == null || this.ctrls == null) { throw new TranslatorException( "Search context, filter, or controls were null. Cannot execute search."); //$NON-NLS-1$ } ArrayList<Column> attributeList = searchDetails.getElementList(); // determine if there is an array value to unwrap for (int i = 0; i < attributeList.size(); i++) { Column col = attributeList.get(i); if (Boolean.valueOf(col.getProperty(LDAPExecutionFactory.UNWRAP, false))) { if (unwrapPos > -1) { throw new TranslatorException( LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12014, col, attributeList.get(unwrapPos))); } unwrapPos = i; } } setRequestControls(null); // Execute the search. executeSearch(); }
// GHH 20080326 - added fetching of DN of result, for directories that // do not include it as an attribute private List<?> getRow(SearchResult result) throws TranslatorException, InvalidNameException { Attributes attrs = result.getAttributes(); ArrayList<Column> attributeList = searchDetails.getElementList(); final List<Object> row = new ArrayList<Object>(attributeList.size()); for (int i = 0; i < attributeList.size(); i++) { Column col = attributeList.get(i); Object val = getValue( col, result, attrs, i == unwrapPos); // GHH 20080326 - added resultDN parameter to call row.add(val); } if (unwrapPos > -1) { Object toUnwrap = row.get(unwrapPos); if (toUnwrap == null) { return row; // missing value } if (toUnwrap instanceof ArrayImpl) { final Object[] val = ((ArrayImpl) toUnwrap).getValues(); if (val.length == 0) { row.set(unwrapPos, null); // empty value } else { unwrapIterator = new Iterator<List<Object>>() { int i = 0; @Override public boolean hasNext() { return i < val.length; } @Override public List<Object> next() { List<Object> newRow = new ArrayList<Object>(row); newRow.set(unwrapPos, val[i++]); return newRow; } @Override public void remove() {} }; if (unwrapIterator.hasNext()) { return unwrapIterator.next(); } } } } return row; }
/** * Helper method for testing the provided LDAPSearchDetails against expected values * * @param searchDetails the LDAPSearchDetails object * @param expectedContextName the expected context name * @param expectedContextFilter the expected context filter string * @param expectedAttrNameList list of expected attribute names * @param expectedCountLimit the expected count limit * @param expectedSearchScope the expected search scope * @param expectedSortKeys the expected sortKeys list. */ public void helpTestSearchDetails( final LDAPSearchDetails searchDetails, final String expectedContextName, final String expectedContextFilter, final List<String> expectedAttrNameList, final long expectedCountLimit, final int expectedSearchScope, final SortKey[] expectedSortKeys) { // Get all of the actual values String contextName = searchDetails.getContextName(); String contextFilter = searchDetails.getContextFilter(); List<Column> attrList = searchDetails.getElementList(); long countLimit = searchDetails.getCountLimit(); int searchScope = searchDetails.getSearchScope(); SortKey[] sortKeys = searchDetails.getSortKeys(); // Compare actual with Expected assertEquals(expectedContextName, contextName); assertEquals(expectedContextFilter, contextFilter); assertEquals(attrList.size(), expectedAttrNameList.size()); Iterator<Column> iter = attrList.iterator(); Iterator<String> eIter = expectedAttrNameList.iterator(); while (iter.hasNext() && eIter.hasNext()) { String actualName = iter.next().getSourceName(); String expectedName = eIter.next(); assertEquals(actualName, expectedName); } assertEquals(expectedCountLimit, countLimit); assertEquals(expectedSearchScope, searchScope); assertArrayEquals(expectedSortKeys, sortKeys); }
/** * Perform the LDAP search against the subcontext, using the filter and search controls * appropriate to the query and model metadata. */ private void executeSearch() throws TranslatorException { String filter = searchDetails.getContextFilter(); try { searchEnumeration = this.ldapCtx.search("", filter, ctrls); // $NON-NLS-1$ } catch (NamingException ne) { final String msg = LDAPPlugin.Util.getString("LDAPSyncQueryExecution.execSearchError"); // $NON-NLS-1$ throw new TranslatorException(ne, msg + " : " + ne.getExplanation()); // $NON-NLS-1$ } catch (Exception e) { final String msg = LDAPPlugin.Util.getString("LDAPSyncQueryExecution.execSearchError"); // $NON-NLS-1$ throw new TranslatorException(e, msg); } }