Author: rareddy
Date: 2012-10-01 15:23:30 -0400 (Mon, 01 Oct 2012)
New Revision: 4496
Modified:
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/IQueryToLdapSearchParser.java
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPDirectSearchQueryExecution.java
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPSearchDetails.java
trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestIQueryToLdapSearchParser.java
Log:
TEIID-2177: Expanding the native query support through extension metadata is expanded to
LDAP tables.
Modified:
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/IQueryToLdapSearchParser.java
===================================================================
---
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/IQueryToLdapSearchParser.java 2012-10-01
17:55:58 UTC (rev 4495)
+++
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/IQueryToLdapSearchParser.java 2012-10-01
19:23:30 UTC (rev 4496)
@@ -40,6 +40,7 @@
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.StringTokenizer;
import javax.naming.directory.SearchControls;
import javax.naming.ldap.SortKey;
@@ -49,9 +50,12 @@
import org.teiid.language.SortSpecification.Ordering;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
+import org.teiid.metadata.AbstractMetadataRecord;
import org.teiid.metadata.Column;
+import org.teiid.metadata.Datatype;
import org.teiid.metadata.Table;
import org.teiid.translator.TranslatorException;
+import org.teiid.translator.TypeFacility;
import org.teiid.translator.ldap.LDAPExecutionFactory.SearchDefaultScope;
@@ -60,6 +64,13 @@
* Utility class which translates a SQL query into an LDAP search.
*/
public class IQueryToLdapSearchParser {
+ private static final String ATTRIBUTES = "attributes"; //$NON-NLS-1$
+ private static final String COUNT_LIMIT = "count-limit"; //$NON-NLS-1$
+ private static final String TIMEOUT = "timeout";//$NON-NLS-1$
+ private static final String SEARCH_SCOPE = "search-scope";//$NON-NLS-1$
+ private static final String CRITERIA = "filter";//$NON-NLS-1$
+ private static final String CONTEXT_NAME = "context-name";//$NON-NLS-1$
+ public static final String TEIID_NATIVE_QUERY = AbstractMetadataRecord.RELATIONAL_URI +
"native-query"; //$NON-NLS-1$
LDAPExecutionFactory executionFactory;
/**
@@ -89,23 +100,31 @@
// TODO - change method for calling RESTRICT to also specify
// object class name (RESTRICT=inetOrgPerson)
public LDAPSearchDetails translateSQLQueryToLDAPSearch(Select query) throws
TranslatorException {
- // Parse SELECT symbols.
- // The columns will be translated into LDAP attributes of interest.
- ArrayList<Column> elementList = getElementsFromSelectSymbols(query);
-
- // Parse FROM table.
- // Only one table is expected here.
- List<TableReference> fromList = query.getFrom();
- Iterator<TableReference> itr = fromList.iterator();
- if(!itr.hasNext()) {
- final String msg =
LDAPPlugin.Util.getString("IQueryToLdapSearchParser.noTablesInFromError");
//$NON-NLS-1$
- throw new TranslatorException(msg);
- }
- TableReference fItm = itr.next();
- if(itr.hasNext()) {
- final String msg =
LDAPPlugin.Util.getString("IQueryToLdapSearchParser.multiItemsInFromError");
//$NON-NLS-1$
- throw new TranslatorException(msg);
- }
+ // Parse SELECT symbols.
+ // The columns will be translated into LDAP attributes of interest.
+ ArrayList<Column> elementList = getElementsFromSelectSymbols(query);
+
+ // Parse FROM table.
+ // Only one table is expected here.
+ List<TableReference> fromList = query.getFrom();
+ Iterator<TableReference> itr = fromList.iterator();
+ if(!itr.hasNext()) {
+ final String msg =
LDAPPlugin.Util.getString("IQueryToLdapSearchParser.noTablesInFromError");
//$NON-NLS-1$
+ throw new TranslatorException(msg);
+ }
+ TableReference fItm = itr.next();
+ if(itr.hasNext()) {
+ final String msg =
LDAPPlugin.Util.getString("IQueryToLdapSearchParser.multiItemsInFromError");
//$NON-NLS-1$
+ throw new TranslatorException(msg);
+ }
+
+ LDAPSearchDetails sd = null;
+ Table table = ((NamedTable)fItm).getMetadataObject();
+ String nativeQuery = table.getProperty(TEIID_NATIVE_QUERY, false);
+ if (nativeQuery != null) {
+ sd = buildRequest(nativeQuery);
+ }
+ else {
String contextName = getContextNameFromFromItem(fItm);
int searchScope = getSearchScopeFromFromItem(fItm);
// GHH 20080326 - added check for RESTRICT parameter in
@@ -142,12 +161,12 @@
}
// Create Search Details
- LDAPSearchDetails sd = new LDAPSearchDetails(contextName, searchScope,
filterBuilder.toString(), sortKeys, countLimit, elementList);
- // Search Details logging
- sd.printDetailsToLog();
+ sd = new LDAPSearchDetails(contextName, searchScope, filterBuilder.toString(),
sortKeys, countLimit, elementList, 0);
+ }
+ // Search Details logging
+ sd.printDetailsToLog();
+ return sd;
- return sd;
-
}
/**
@@ -598,5 +617,73 @@
return expr.getMetadataObject();
}
+ public LDAPSearchDetails buildRequest(String query) {
+ ArrayList<String> attributes = new ArrayList<String>();
+ ArrayList<Column> columns = new ArrayList<Column>();
+ String contextName = null;
+ String criteria = ""; //$NON-NLS-1$
+ String searchScope = this.executionFactory.getSearchDefaultScope().name();
+ int timeLimit = 0;
+ long countLimit = 0;
+
+ StringTokenizer st = new StringTokenizer(query, ";"); //$NON-NLS-1$
+ while (st.hasMoreTokens()) {
+ String var = st.nextToken();
+ int index = var.indexOf('=');
+ if (index == -1) {
+ continue;
+ }
+ String key = var.substring(0, index).trim().toLowerCase();
+ String value = var.substring(index+1).trim();
+
+ if (key.equalsIgnoreCase(CONTEXT_NAME)) {
+ contextName = value;
+ }
+ else if (key.equalsIgnoreCase(CRITERIA)) {
+ criteria = value;
+ }
+ else if (key.equalsIgnoreCase(SEARCH_SCOPE)) {
+ searchScope = value;
+ }
+ else if (key.equalsIgnoreCase(TIMEOUT)) {
+ timeLimit = Integer.parseInt(value);
+ }
+ else if (key.equalsIgnoreCase(COUNT_LIMIT)) {
+ countLimit = Long.parseLong(value);
+ }
+ else if (key.equalsIgnoreCase(ATTRIBUTES)) {
+ StringTokenizer attrTokens = new StringTokenizer(value, ",");
//$NON-NLS-1$
+ while(attrTokens.hasMoreElements()) {
+ String name = attrTokens.nextToken().trim();
+ attributes.add(name);
+
+ Column column = new Column();
+ column.setName(name);
+ Datatype type = new Datatype();
+ type.setName(TypeFacility.RUNTIME_NAMES.OBJECT);
+ type.setJavaClassName(Object.class.getCanonicalName());
+ column.setDatatype(type, true);
+ columns.add(column);
+ }
+ }
+ }
+
+ int searchScopeInt = buildSearchScope(searchScope);
+ return new LDAPSearchDetails(contextName, searchScopeInt, criteria, null, countLimit,
columns, timeLimit);
+ }
+ private int buildSearchScope(String searchScope) {
+ int searchScopeInt = 0;
+ // this could be one of OBJECT_SCOPE, ONELEVEL_SCOPE, SUBTREE_SCOPE
+ if (searchScope.equalsIgnoreCase("OBJECT_SCOPE")) { //$NON-NLS-1$
+ searchScopeInt = SearchControls.OBJECT_SCOPE;
+ }
+ else if (searchScope.equalsIgnoreCase("ONELEVEL_SCOPE")) {//$NON-NLS-1$
+ searchScopeInt = SearchControls.ONELEVEL_SCOPE;
+ }
+ else if (searchScope.equalsIgnoreCase("SUBTREE_SCOPE")) {//$NON-NLS-1$
+ searchScopeInt = SearchControls.SUBTREE_SCOPE;
+ }
+ return searchScopeInt;
+ }
}
Modified:
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPDirectSearchQueryExecution.java
===================================================================
---
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPDirectSearchQueryExecution.java 2012-10-01
17:55:58 UTC (rev 4495)
+++
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPDirectSearchQueryExecution.java 2012-10-01
19:23:30 UTC (rev 4496)
@@ -23,28 +23,17 @@
import java.util.ArrayList;
import java.util.List;
-import java.util.StringTokenizer;
import javax.naming.directory.SearchControls;
import javax.naming.ldap.LdapContext;
import org.teiid.language.Argument;
-import org.teiid.metadata.Column;
-import org.teiid.metadata.Datatype;
import org.teiid.translator.DataNotAvailableException;
import org.teiid.translator.ExecutionContext;
import org.teiid.translator.ProcedureExecution;
import org.teiid.translator.TranslatorException;
-import org.teiid.translator.TypeFacility;
public class LDAPDirectSearchQueryExecution extends LDAPSyncQueryExecution implements
ProcedureExecution {
-
- private static final String ATTRIBUTES = "attributes"; //$NON-NLS-1$
- private static final String COUNT_LIMIT = "count-limit"; //$NON-NLS-1$
- private static final String TIMEOUT = "timeout";//$NON-NLS-1$
- private static final String SEARCH_SCOPE = "search-scope";//$NON-NLS-1$
- private static final String CRITERIA = "filter";//$NON-NLS-1$
- private static final String CONTEXT_NAME = "context-name";//$NON-NLS-1$
private List<Argument> arguments;
@@ -55,94 +44,23 @@
@Override
public void execute() throws TranslatorException {
- this.delegate = buildRequest();
- this.delegate.execute();
- }
-
- private LDAPQueryExecution buildRequest() throws TranslatorException {
String query = (String)arguments.get(0).getArgumentValue().getValue();
+ IQueryToLdapSearchParser parser = new IQueryToLdapSearchParser(this.executionFactory);
+ LDAPSearchDetails details = parser.buildRequest(query);
+ // Create and configure the new search context.
+ LdapContext context = createSearchContext(details.getContextName());
- ArrayList<String> attributes = new ArrayList<String>();
- ArrayList<Column> columns = new ArrayList<Column>();
- String contextName = null;
- String criteria = ""; //$NON-NLS-1$
- String searchScope = this.executionFactory.getSearchDefaultScope().name();
- int timeLimit = 0;
- long countLimit = 0;
-
- StringTokenizer st = new StringTokenizer(query, ";"); //$NON-NLS-1$
- while (st.hasMoreTokens()) {
- String var = st.nextToken();
- int index = var.indexOf('=');
- if (index == -1) {
- continue;
- }
- String key = var.substring(0, index).trim().toLowerCase();
- String value = var.substring(index+1).trim();
-
- if (key.equalsIgnoreCase(CONTEXT_NAME)) {
- contextName = value;
- }
- else if (key.equalsIgnoreCase(CRITERIA)) {
- criteria = value;
- }
- else if (key.equalsIgnoreCase(SEARCH_SCOPE)) {
- searchScope = value;
- }
- else if (key.equalsIgnoreCase(TIMEOUT)) {
- timeLimit = Integer.parseInt(value);
- }
- else if (key.equalsIgnoreCase(COUNT_LIMIT)) {
- countLimit = Long.parseLong(value);
- }
- else if (key.equalsIgnoreCase(ATTRIBUTES)) {
- StringTokenizer attrTokens = new StringTokenizer(value, ",");
//$NON-NLS-1$
- while(attrTokens.hasMoreElements()) {
- String name = attrTokens.nextToken().trim();
- attributes.add(name);
-
- Column column = new Column();
- column.setName(name);
- Datatype type = new Datatype();
- type.setName(TypeFacility.RUNTIME_NAMES.OBJECT);
- type.setJavaClassName(Object.class.getCanonicalName());
- column.setDatatype(type, true);
- columns.add(column);
- }
- }
- }
-
- int searchScopeInt = buildSearchScope(searchScope);
-
// build search controls
SearchControls controls = new SearchControls();
- controls.setSearchScope(searchScopeInt);
- controls.setTimeLimit(timeLimit);
- controls.setCountLimit(countLimit);
- controls.setReturningAttributes(attributes.toArray(new String[attributes.size()]));
+ controls.setSearchScope(details.getSearchScope());
+ controls.setTimeLimit(details.getTimeLimit());
+ controls.setCountLimit(details.getCountLimit());
+ controls.setReturningAttributes(details.getAttributes());
- LDAPSearchDetails searchDetails = new LDAPSearchDetails(contextName, searchScopeInt,
criteria, null, countLimit, columns);
-
- // Create and configure the new search context.
- LdapContext context = createSearchContext(contextName);
- return new LDAPQueryExecution(context, searchDetails, controls, this.executionFactory,
this.executionContext);
+ this.delegate = new LDAPQueryExecution(context, details, controls,
this.executionFactory, this.executionContext);
+ this.delegate.execute();
}
- private int buildSearchScope(String searchScope) {
- int searchScopeInt = 0;
- // this could be one of OBJECT_SCOPE, ONELEVEL_SCOPE, SUBTREE_SCOPE
- if (searchScope.equalsIgnoreCase("OBJECT_SCOPE")) { //$NON-NLS-1$
- searchScopeInt = SearchControls.OBJECT_SCOPE;
- }
- else if (searchScope.equalsIgnoreCase("ONELEVEL_SCOPE")) {//$NON-NLS-1$
- searchScopeInt = SearchControls.ONELEVEL_SCOPE;
- }
- else if (searchScope.equalsIgnoreCase("SUBTREE_SCOPE")) {//$NON-NLS-1$
- searchScopeInt = SearchControls.SUBTREE_SCOPE;
- }
- return searchScopeInt;
- }
-
@Override
public List<?> next() throws TranslatorException, DataNotAvailableException {
List<?> vals = super.next();
Modified:
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPSearchDetails.java
===================================================================
---
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPSearchDetails.java 2012-10-01
17:55:58 UTC (rev 4495)
+++
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPSearchDetails.java 2012-10-01
19:23:30 UTC (rev 4496)
@@ -48,6 +48,7 @@
// If limit is set to -1, this means no limit (return all rows)
private long limit;
private ArrayList<Column> elementList;
+ private int timeLimit;
/**
* Constructor
@@ -59,7 +60,7 @@
* @param limit
* @param elementList
*/
- public LDAPSearchDetails(String name, int searchScope, String filter, SortKey[] keys,
long limit, ArrayList elementList) {
+ public LDAPSearchDetails(String name, int searchScope, String filter, SortKey[] keys,
long limit, ArrayList elementList, int timeLimit) {
this.contextName = name;
this.searchScope = searchScope;
@@ -67,6 +68,7 @@
this.keys = keys;
this.limit = limit;
this.elementList = elementList;
+ this.timeLimit = timeLimit;
}
/**
@@ -179,4 +181,16 @@
}
}
}
+
+ public int getTimeLimit() {
+ return this.timeLimit;
+ }
+
+ public String[] getAttributes() {
+ ArrayList<String> attributes = new ArrayList<String>();
+ for (Column c:elementList) {
+ attributes.add(c.getName());
+ }
+ return attributes.toArray(new String[attributes.size()]);
+ }
}
Modified:
trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestIQueryToLdapSearchParser.java
===================================================================
---
trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestIQueryToLdapSearchParser.java 2012-10-01
17:55:58 UTC (rev 4495)
+++
trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestIQueryToLdapSearchParser.java 2012-10-01
19:23:30 UTC (rev 4496)
@@ -21,8 +21,6 @@
*/
package org.teiid.translator.ldap;
-import static org.mockito.Mockito.mock;
-
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -34,23 +32,18 @@
import org.teiid.cdk.CommandBuilder;
import org.teiid.core.types.DataTypeManager;
-import org.teiid.dqp.internal.datamgr.RuntimeMetadataImpl;
import org.teiid.language.Command;
import org.teiid.language.Select;
import org.teiid.metadata.Column;
+import org.teiid.metadata.Column.SearchType;
import org.teiid.metadata.MetadataStore;
-import org.teiid.metadata.RuntimeMetadata;
import org.teiid.metadata.Schema;
import org.teiid.metadata.Table;
-import org.teiid.metadata.Column.SearchType;
import org.teiid.query.metadata.CompositeMetadataStore;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.unittest.RealMetadataFactory;
import org.teiid.translator.TranslatorException;
-import org.teiid.translator.ldap.IQueryToLdapSearchParser;
-import org.teiid.translator.ldap.LDAPExecutionFactory;
-import org.teiid.translator.ldap.LDAPSearchDetails;
/**
@@ -252,16 +245,34 @@
helpTestSearchDetails(searchDetails, expectedContextName, expectedContextFilter,
expectedAttrNameList,
expectedCountLimit, expectedSearchScope, expectedSortKeys);
}
+
+ public void testNativeQueryExtension() throws Exception {
+ LDAPSearchDetails searchDetails = helpGetSearchDetails("SELECT * FROM
LdapModel.Employee"); //$NON-NLS-1$
+
+ String expectedContextName = "corporate"; //$NON-NLS-1$
+ String expectedContextFilter = "(objectClass=*)"; //$NON-NLS-1$
+
+ List expectedAttrNameList = new ArrayList();
+ expectedAttrNameList.add("uid"); //$NON-NLS-1$
+ expectedAttrNameList.add("cn"); //$NON-NLS-1$
+
+ long expectedCountLimit = 5;
+ int expectedSearchScope = SearchControls.ONELEVEL_SCOPE;
+ SortKey[] expectedSortKeys = null;
+
+ helpTestSearchDetails(searchDetails, expectedContextName, expectedContextFilter,
expectedAttrNameList,
+ expectedCountLimit, expectedSearchScope, expectedSortKeys);
+
+ }
private LDAPSearchDetails helpGetSearchDetails(String queryString) throws
TranslatorException {
QueryMetadataInterface metadata = exampleLdap();
- RuntimeMetadata rm = new RuntimeMetadataImpl(metadata);
- LDAPExecutionFactory config = mock(LDAPExecutionFactory.class);
+ Select query = (Select)getCommand(queryString, metadata);
+ LDAPExecutionFactory config = new LDAPExecutionFactory();
+
IQueryToLdapSearchParser searchParser = new IQueryToLdapSearchParser(config);
-
- Select query = (Select)getCommand(queryString, metadata);
LDAPSearchDetails searchDetails =
searchParser.translateSQLQueryToLDAPSearch(query);
return searchDetails;
@@ -301,6 +312,19 @@
cols.get(i).setSearchType(SearchType.Unsearchable);
}
+ Table employees = RealMetadataFactory.createPhysicalGroup("Employee",
ldapModel); //$NON-NLS-1$
+ List<Column> employeeCols = RealMetadataFactory.createElements(employees,
elemNames, elemTypes);
+ for(int i=0; i<2; i++) {
+ Column obj = employeeCols.get(i);
+ obj.setNameInSource(nameInSource[i]);
+ }
+
+ // Set column-specific properties
+ for(int i=1; i<2; i++) {
+ employeeCols.get(i).setSearchType(SearchType.Unsearchable);
+ }
+ employees.setProperty(IQueryToLdapSearchParser.TEIID_NATIVE_QUERY,
"context-name=corporate;filter=(objectClass=*);count-limit=5;timout=6;search-scope=ONELEVEL_SCOPE;attributes=uid,cn");
//$NON-NLS-1$
+
// Create the facade from the store
return new TransformationMetadata(null, new
CompositeMetadataStore(metadataStore), null, RealMetadataFactory.SFM.getSystemFunctions(),
null);
}