Author: shawkins
Date: 2012-10-03 15:05:34 -0400 (Wed, 03 Oct 2012)
New Revision: 4511
Modified:
trunk/common-core/src/main/java/org/teiid/core/util/StringUtil.java
trunk/common-core/src/test/java/org/teiid/core/util/TestStringUtil.java
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/IQueryToLdapSearchParser.java
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPDirectCreateUpdateDeleteQueryExecution.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/LDAPExecutionFactory.java
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPPlugin.java
trunk/connectors/translator-ldap/src/main/resources/org/teiid/translator/ldap/i18n.properties
trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestIQueryToLdapSearchParser.java
trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestLDAPDirectQueryExecution.java
Log:
TEIID-2177 adding ldap canned queries
Modified: trunk/common-core/src/main/java/org/teiid/core/util/StringUtil.java
===================================================================
--- trunk/common-core/src/main/java/org/teiid/core/util/StringUtil.java 2012-10-03
16:54:06 UTC (rev 4510)
+++ trunk/common-core/src/main/java/org/teiid/core/util/StringUtil.java 2012-10-03
19:05:34 UTC (rev 4511)
@@ -109,18 +109,6 @@
return LINE_SEPARATOR;
}
- /**
- * Utility to return a string enclosed in ''.
- * Creation date: (12/2/99 12:05:10 PM)
- */
- public static String enclosedInSingleQuotes(String aString) {
- StringBuffer sb = new StringBuffer();
- sb.append(SINGLE_QUOTE);
- sb.append(aString);
- sb.append(SINGLE_QUOTE);
- return sb.toString();
- }
-
/**
* Join string pieces and separate with a delimiter. Similar to the perl function of
* the same name. If strings or delimiter are null, null is returned. Otherwise, at
@@ -131,7 +119,7 @@
* @param delimiter Delimiter to put between string pieces
* @return One merged string
*/
- public static String join(List strings, String delimiter) {
+ public static String join(List<String> strings, String delimiter) {
if(strings == null || delimiter == null) {
return null;
}
@@ -147,7 +135,7 @@
// put the piece and a delimiter after it. An iterator is used to walk the list.
int most = strings.size()-1;
if(strings.size() > 1) {
- Iterator iter = strings.iterator();
+ Iterator<String> iter = strings.iterator();
for(int i=0; i<most; i++) {
str.append(iter.next());
str.append(delimiter);
@@ -215,64 +203,6 @@
return l;
}
- /**
- * Break a string into pieces based on matching the full delimiter string in the
text.
- * The delimiter is not included in the returned strings.
- * @param target The text to break up.
- * @param delimiter The sub-string which is used to break the target.
- * @return List of String from the target.
- */
- public static List<String> splitOnEntireString(String target, String delimiter)
{
- ArrayList<String> result = new ArrayList<String>();
- if (delimiter.length() > 0) {
- int index = 0;
- int indexOfNextMatch = target.indexOf(delimiter);
- while (indexOfNextMatch > -1) {
- result.add(target.substring(index, indexOfNextMatch));
- index = indexOfNextMatch + delimiter.length();
- indexOfNextMatch = target.indexOf(delimiter, index);
- }
- if (index <= target.length()) {
- result.add(target.substring(index));
- }
- } else {
- result.add(target);
- }
- return result;
- }
-
- /**
- * Split a string into pieces based on delimiters preserving spaces in
- * quoted substring as on element in the returned list. The delimiters are
- * not included in the returned strings.
- * @see #join
- *
- * @param str Full string
- * @param splitter Characters to split on
- * @return List of String pieces from full string
- */
- public static List splitPreservingQuotedSubstring(String str, String splitter) {
- ArrayList l = new ArrayList();
- StringTokenizer tokens = new StringTokenizer(str, splitter);
- StringBuffer token = new StringBuffer();
- while(tokens.hasMoreTokens()) {
- token.setLength(0);
- token.append(tokens.nextToken());
- if ( token.charAt(0) == '"' ) {
- token.deleteCharAt(0);
- while ( tokens.hasMoreTokens() ) {
- token.append(Constants.SPACE + tokens.nextToken());
- if ( token.charAt(token.length() -1) == '"' ) {
- token.deleteCharAt(token.length() - 1);
- break;
- }
- }
- }
- l.add(token.toString().trim());
- }
- return l;
- }
-
/*
* Replace a single occurrence of the search string with the replace string
* in the source string. If any of the strings is null or the search string
@@ -353,10 +283,10 @@
if (strLength > maxCharPerLine) {
StringBuffer sb = new
StringBuffer(str.length()+(strLength/maxCharPerLine)+1);
strLength = 0;
- List tokens = StringUtil.split(str,Constants.SPACE);
- Iterator itr = tokens.iterator();
+ List<String> tokens = StringUtil.split(str,Constants.SPACE);
+ Iterator<String> itr = tokens.iterator();
while (itr.hasNext()) {
- String token = (String) itr.next();
+ String token = itr.next();
if ( strLength+token.length() > maxCharPerLine ) {
// sb.append(getLineSeparator());
sb.append(Constants.NEW_LINE);
@@ -389,36 +319,6 @@
return l;
}
- /**
- * Return the number of tokens in a string that are seperated by the delimiter.
- *
- * @param str String to be tokenized
- * @param delimiter Characters which are delimit tokens
- * @return Number of tokens seperated by the delimiter
- */
- public static int getTokenCount(String str, String delimiter) {
- StringTokenizer tokens = new StringTokenizer(str, delimiter);
- return tokens.countTokens();
- }
-
- /**
- * Return the number of occurrences of token string that occurs in input string.
- * Note: token is case sensitive.
- *
- * @param input
- * @param token
- * @return int
- */
- public static int occurrences(String input, String token) {
- int num = 0;
- int index = input.indexOf(token);
- while (index >= 0) {
- num++;
- index = input.indexOf(token, index+1);
- }
- return num;
- }
-
/**
* Return the last token in the string.
*
@@ -473,32 +373,6 @@
* <li>"SQLIndexT" is converted to "SQL Index
T"</li>
* <li>"SQLIndex T" is converted to "SQL Index
T"</li>
* <li>"SQLIndex t" is converted to "SQL Index
T"</li>
- *
- * @param str String to be converted; may be null
- * @return the displayable form of <code>str</code>, or an empty string
if
- * <code>str</code> is either null or zero-length; never null
- */
- public static String computeDisplayableForm(String str) {
- return computeDisplayableForm(str, Constants.EMPTY_STRING);
- }
-
- /**
- * Compute a displayable form of the specified string. This algorithm
- * attempts to create a string that contains words that begin with uppercase
- * characters and that are separated by a single space. For example,
- * the following are the outputs of some sample inputs:
- * <li>"aName" is converted to "A Name"</li>
- * <li>"Name" is converted to "Name"</li>
- * <li>"NAME" is converted to "NAME"</li>
- * <li>"theName" is converted to "The Name"</li>
- * <li>"theBIGName" is converted to "The BIG
Name"</li>
- * <li>"the BIG Name" is converted to "The BIG
Name"</li>
- * <li>"the big Name" is converted to "The Big
Name"</li>
- * <li>"theBIG" is converted to "The BIG"</li>
- * <li>"SQLIndex" is converted to "SQL Index"</li>
- * <li>"SQLIndexT" is converted to "SQL Index
T"</li>
- * <li>"SQLIndex T" is converted to "SQL Index
T"</li>
- * <li>"SQLIndex t" is converted to "SQL Index
T"</li>
* <p>
* An exception is "MetaMatrix", which is always treated as a single word
* </p>
@@ -572,33 +446,6 @@
return newName.toString();
}
- /**
- * @since 3.0
- */
- public static String computeDisplayableFormOfConstant(final String text) {
- return computeDisplayableFormOfConstant(text, Constants.EMPTY_STRING);
- }
-
- /**
- * @since 3.0
- */
- public static String computeDisplayableFormOfConstant(final String text, final String
defaultValue) {
- if (text == null || text.length() == 0) {
- return defaultValue;
- }
- final StringBuffer buf = new StringBuffer();
- String token;
- for (final StringTokenizer iter = new StringTokenizer(text, "_");
iter.hasMoreTokens();) { //$NON-NLS-1$
- token = iter.nextToken().toLowerCase();
- if (buf.length() > 0) {
- buf.append(' ');
- }
- buf.append(Character.toUpperCase(token.charAt(0)));
- buf.append(token.substring(1));
- }
- return buf.toString();
- }
-
public static String computePluralForm(String str) {
return computePluralForm(str, Constants.EMPTY_STRING);
}
@@ -786,28 +633,6 @@
}
/**
- * Removes extraneous whitespace from a string. By it's nature, it will be
trimmed also.
- * @param raw
- * @return
- * @since 5.0
- */
- public static String collapseWhitespace(String raw) {
- StringBuffer rv = new StringBuffer(raw.length());
-
- StringTokenizer izer = new StringTokenizer(raw, " "); //$NON-NLS-1$
- while (izer.hasMoreTokens()) {
- String tok = izer.nextToken();
- // Added one last check here so we don't append a "space" on
the end of the string
- rv.append(tok);
- if( izer.hasMoreTokens() ) {
- rv.append(' ');
- }
- } // endwhile
-
- return rv.toString();
- }
-
- /**
* If input == null OR input.length() < desiredLength, pad to desiredLength with
spaces.
* If input.length() > desiredLength, chop at desiredLength.
* @param input Input text
@@ -1012,4 +837,32 @@
}
}
+ public static List<String> tokenize(String str, char delim) {
+ ArrayList<String> result = new ArrayList<String>();
+ StringBuilder current = new StringBuilder();
+ boolean escaped = false;
+ for (int i = 0; i < str.length(); i++) {
+ char c = str.charAt(i);
+ if (c == delim) {
+ if (escaped) {
+ current.append(c);
+ escaped = false;
+ } else {
+ escaped = true;
+ }
+ } else {
+ if (escaped && current.length() > 0) {
+ result.add(current.toString());
+ current.setLength(0);
+ escaped = false;
+ }
+ current.append(c);
+ }
+ }
+ if (current.length()>0) {
+ result.add(current.toString());
+ }
+ return result;
+ }
+
}
Modified: trunk/common-core/src/test/java/org/teiid/core/util/TestStringUtil.java
===================================================================
--- trunk/common-core/src/test/java/org/teiid/core/util/TestStringUtil.java 2012-10-03
16:54:06 UTC (rev 4510)
+++ trunk/common-core/src/test/java/org/teiid/core/util/TestStringUtil.java 2012-10-03
19:05:34 UTC (rev 4511)
@@ -37,12 +37,6 @@
*/
public class TestStringUtil {
- // ********* H E L P E R M E T H O D S *********
- public void helpTestEncloseInSingleQuotes(String input, String expectedResult){
- String result = StringUtil.enclosedInSingleQuotes(input);
- assertEquals("Unexpected encloseInSignleQuotes result", expectedResult,
result ); //$NON-NLS-1$
- }
-
public void helpTestComputeDisplayableForm(String input, String expectedResult){
String result = StringUtil.computeDisplayableForm(input, input);
assertEquals("Unexpected ComputeDisplayableForm result", expectedResult,
result ); //$NON-NLS-1$
@@ -73,11 +67,6 @@
assertEquals("Unexpected TruncString result", expectedResult, result );
//$NON-NLS-1$
}
- // ********* T E S T S U I T E M E T H O D S *********
- @Test public void testEncloseInSingleQuotes() {
- helpTestEncloseInSingleQuotes("testString",
"\'testString\'"); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
@Test public void testComputeDisplayableForm1() {
helpTestComputeDisplayableForm("testString", "Test String");
//$NON-NLS-1$ //$NON-NLS-2$
}
@@ -228,41 +217,6 @@
assertEquals(" are 7 tokens.", tokens.get(6)); //$NON-NLS-1$
}
- @Test public void testSplitOnEntireString() {
- List<String> result =
StringUtil.splitOnEntireString("thisNEXTcanNEXTbe", "NEXT");
//$NON-NLS-1$ //$NON-NLS-2$
- assertEquals(3, result.size());
- assertEquals("this", result.get(0)); //$NON-NLS-1$
- assertEquals("can", result.get(1)); //$NON-NLS-1$
- assertEquals("be", result.get(2)); //$NON-NLS-1$
-
- }
-
- @Test public void testSplitOnEntireStringEmptyString() {
- List<String> result = StringUtil.splitOnEntireString("",
"NEXT"); //$NON-NLS-1$ //$NON-NLS-2$
- assertEquals(1, result.size());
- assertEquals("", result.get(0)); //$NON-NLS-1$
- }
-
- @Test public void testSplitOnEntireStringEntireStringIsDelimiter() {
- List<String> result = StringUtil.splitOnEntireString("NEXT",
"NEXT"); //$NON-NLS-1$ //$NON-NLS-2$
- assertEquals(2, result.size());
- assertEquals("", result.get(0)); //$NON-NLS-1$
- assertEquals("", result.get(1)); //$NON-NLS-1$
- }
-
- @Test public void testSplitOnEntireStringEmptyDelimiter() {
- List<String> result = StringUtil.splitOnEntireString("test",
""); //$NON-NLS-1$ //$NON-NLS-2$
- assertEquals(1, result.size());
- assertEquals("test", result.get(0)); //$NON-NLS-1$
- }
-
- @Test public void testSplitOnEntireStringEndsWithDelimiter() {
- List<String> result = StringUtil.splitOnEntireString("testNEXT",
"NEXT"); //$NON-NLS-1$ //$NON-NLS-2$
- assertEquals(2, result.size());
- assertEquals("test", result.get(0)); //$NON-NLS-1$
- assertEquals("", result.get(1)); //$NON-NLS-1$
- }
-
@Test public void testIndexOfIgnoreCase() {
String text = "test"; //$NON-NLS-1$
assertEquals(-1,StringUtil.indexOfIgnoreCase(null,text));
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-03
16:54:06 UTC (rev 4510)
+++
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/IQueryToLdapSearchParser.java 2012-10-03
19:05:34 UTC (rev 4511)
@@ -45,12 +45,12 @@
import javax.naming.directory.SearchControls;
import javax.naming.ldap.SortKey;
+import org.teiid.core.util.StringUtil;
import org.teiid.language.*;
import org.teiid.language.Comparison.Operator;
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;
@@ -70,7 +70,6 @@
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;
/**
@@ -119,50 +118,43 @@
}
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
- // NameInSource of from item
- String classRestriction = getRestrictToNamedClass(fItm);
-
- // Parse the WHERE clause.
- // Create an equivalent LDAP search filter.
- List<String> searchStringList = new LinkedList<String>();
- searchStringList = getSearchFilterFromWhereClause(query.getWhere(),
searchStringList);
- StringBuilder filterBuilder = new StringBuilder();
- for (String string : searchStringList) {
- filterBuilder.append(string);
- }
- // GHH 20080326 - if there is a class restriction,
- // add it to the search filter
- if (classRestriction != null && classRestriction.trim().length()>0) {
- filterBuilder.insert(0,
"(&").append("(objectClass=").append(classRestriction).append("))");
//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
-
- // Parse the ORDER BY clause.
- // Create an ordered sort list.
- OrderBy orderBy = query.getOrderBy();
- // Referenced the JNDI standard...arguably, this should not be done inside this
- // class, and we should make our own key class. In practice, this makes things
simpler.
- SortKey[] sortKeys = getSortKeysFromOrderByClause(orderBy);
-
- // Parse LIMIT clause.
- // Note that offsets are not supported.
- Limit limit = query.getLimit();
- long countLimit = -1;
- if(limit != null) {
- countLimit = limit.getRowLimit();
- }
-
- // Create Search Details
- sd = new LDAPSearchDetails(contextName, searchScope, filterBuilder.toString(),
sortKeys, countLimit, elementList, 0);
- }
+ String contextName = getContextNameFromFromItem(fItm);
+ int searchScope = getSearchScopeFromFromItem(fItm);
+ // GHH 20080326 - added check for RESTRICT parameter in
+ // NameInSource of from item
+ String classRestriction = getRestrictToNamedClass(fItm);
+
+ // Parse the WHERE clause.
+ // Create an equivalent LDAP search filter.
+ List<String> searchStringList = new LinkedList<String>();
+ searchStringList = getSearchFilterFromWhereClause(query.getWhere(), searchStringList);
+ StringBuilder filterBuilder = new StringBuilder();
+ for (String string : searchStringList) {
+ filterBuilder.append(string);
+ }
+ // GHH 20080326 - if there is a class restriction,
+ // add it to the search filter
+ if (classRestriction != null && classRestriction.trim().length()>0) {
+ filterBuilder.insert(0,
"(&").append("(objectClass=").append(classRestriction).append("))");
//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ // Parse the ORDER BY clause.
+ // Create an ordered sort list.
+ OrderBy orderBy = query.getOrderBy();
+ // Referenced the JNDI standard...arguably, this should not be done inside this
+ // class, and we should make our own key class. In practice, this makes things
simpler.
+ SortKey[] sortKeys = getSortKeysFromOrderByClause(orderBy);
+
+ // Parse LIMIT clause.
+ // Note that offsets are not supported.
+ Limit limit = query.getLimit();
+ long countLimit = -1;
+ if(limit != null) {
+ countLimit = limit.getRowLimit();
+ }
+
+ // Create Search Details
+ sd = new LDAPSearchDetails(contextName, searchScope, filterBuilder.toString(),
sortKeys, countLimit, elementList, 0);
// Search Details logging
sd.printDetailsToLog();
return sd;
@@ -371,42 +363,33 @@
expressionName = mdIDElement.getName();
}
} else if(e instanceof Literal) {
- try {
- if(((Literal)e).getType().equals(Class.forName(Timestamp.class.getName()))) {
- LogManager.logTrace(LogConstants.CTX_CONNECTOR, "Found an expression that uses
timestamp; converting to LDAP string format."); //$NON-NLS-1$
- Timestamp ts = (Timestamp)((Literal)e).getValue();
- Date dt = new Date(ts.getTime());
- //TODO: Fetch format if provided.
- SimpleDateFormat sdf = new
SimpleDateFormat(LDAPConnectorConstants.ldapTimestampFormat);
- expressionName = sdf.format(dt);
- LogManager.logTrace(LogConstants.CTX_CONNECTOR, "Timestamp to stsring is:
" + expressionName); //$NON-NLS-1$
- }
- else {
- expressionName = ((Literal)e).getValue().toString();
- }
- } catch (ClassNotFoundException cce) {
- final String msg =
LDAPPlugin.Util.getString("IQueryToLdapSearchParser.timestampClassNotFoundError");
//$NON-NLS-1$
- throw new TranslatorException(cce, msg);
- }
-
+ expressionName = getExpressionString((Literal)e);
} else {
- if(e instanceof AggregateFunction) {
- LogManager.logError(LogConstants.CTX_CONNECTOR,
LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12001));
- } else if(e instanceof Function) {
- LogManager.logError(LogConstants.CTX_CONNECTOR,
LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12005));
- } else if(e instanceof ScalarSubquery) {
- LogManager.logError(LogConstants.CTX_CONNECTOR,
LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12006));
- } else if (e instanceof SearchedCase) {
- LogManager.logError(LogConstants.CTX_CONNECTOR,
LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12007));
- }
- final String msg =
LDAPPlugin.Util.getString("IQueryToLdapSearchParser.unsupportedElementError");
//$NON-NLS-1$
+ final String msg =
LDAPPlugin.Util.getString("IQueryToLdapSearchParser.unsupportedElementError",
e.getClass().getSimpleName()); //$NON-NLS-1$
throw new TranslatorException(msg + e.toString());
}
expressionName = escapeReservedChars(expressionName);
return expressionName;
}
+
+ static String getExpressionString(Literal l) {
+ if(l.getValue() instanceof Timestamp) {
+ LogManager.logTrace(LogConstants.CTX_CONNECTOR, "Found an expression that uses
timestamp; converting to LDAP string format."); //$NON-NLS-1$
+ Timestamp ts = (Timestamp)l.getValue();
+ Date dt = new Date(ts.getTime());
+ //TODO: Fetch format if provided.
+ SimpleDateFormat sdf = new
SimpleDateFormat(LDAPConnectorConstants.ldapTimestampFormat);
+ String expressionName = sdf.format(dt);
+ LogManager.logTrace(LogConstants.CTX_CONNECTOR, "Timestamp to string is: " +
expressionName); //$NON-NLS-1$
+ return expressionName;
+ }
+ if (l.getValue() != null) {
+ return l.getValue().toString();
+ }
+ return "null"; //$NON-NLS-1$
+ }
- private String escapeReservedChars(String expr) {
+ static String escapeReservedChars(String expr) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < expr.length(); i++) {
char curChar = expr.charAt(i);
@@ -617,23 +600,21 @@
return expr.getMetadataObject();
}
- public LDAPSearchDetails buildRequest(String query) {
+ public LDAPSearchDetails buildRequest(String query) throws TranslatorException {
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();
+ long countLimit = -1;
+ List<String> parts = StringUtil.tokenize(query, ';');
+ for (String var : parts) {
int index = var.indexOf('=');
if (index == -1) {
- continue;
+ throw new TranslatorException(LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12013, var));
}
- String key = var.substring(0, index).trim().toLowerCase();
+ String key = var.substring(0, index).trim();
String value = var.substring(index+1).trim();
if (key.equalsIgnoreCase(CONTEXT_NAME)) {
@@ -665,6 +646,8 @@
column.setDatatype(type, true);
columns.add(column);
}
+ } else {
+ throw new TranslatorException(LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12013, var));
}
}
Modified:
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPDirectCreateUpdateDeleteQueryExecution.java
===================================================================
---
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPDirectCreateUpdateDeleteQueryExecution.java 2012-10-03
16:54:06 UTC (rev 4510)
+++
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPDirectCreateUpdateDeleteQueryExecution.java 2012-10-03
19:05:34 UTC (rev 4511)
@@ -22,6 +22,7 @@
package org.teiid.translator.ldap;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;
@@ -45,27 +46,29 @@
protected LDAPExecutionFactory executionFactory;
protected ExecutionContext executionContext;
private int updateCount = -1;
+ private boolean returnsArray = true;
+ private String query;
- public LDAPDirectCreateUpdateDeleteQueryExecution(List<Argument> arguments,
LDAPExecutionFactory factory, ExecutionContext executionContext, LdapContext connection)
{
+ public LDAPDirectCreateUpdateDeleteQueryExecution(List<Argument> arguments,
LDAPExecutionFactory factory, ExecutionContext executionContext, LdapContext connection,
String query, boolean returnsArray) {
this.arguments = arguments;
this.executionFactory = factory;
this.executionContext = executionContext;
this.ldapConnection = connection;
+ this.query = query;
+ this.returnsArray = returnsArray;
}
@Override
public void execute() throws TranslatorException {
- String query = (String)arguments.get(0).getArgumentValue().getValue();
String firstToken = null;
StringTokenizer st = new StringTokenizer(query, ";"); //$NON-NLS-1$
if (st.hasMoreTokens()) {
firstToken = st.nextToken();
- if (!firstToken.equalsIgnoreCase("create") &&
!firstToken.equalsIgnoreCase("update") &&
!firstToken.equalsIgnoreCase("delete")) { //$NON-NLS-1$ //$NON-NLS-2$
//$NON-NLS-3$
- throw new TranslatorException(LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12009));
- }
}
-
+ if (firstToken == null || (!firstToken.equalsIgnoreCase("create") &&
!firstToken.equalsIgnoreCase("update") &&
!firstToken.equalsIgnoreCase("delete"))) { //$NON-NLS-1$ //$NON-NLS-2$
//$NON-NLS-3$
+ throw new TranslatorException(LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12009));
+ }
LdapContext ldapCtx = null;
try {
ldapCtx = (LdapContext)this.ldapConnection.lookup(""); //$NON-NLS-1$
@@ -75,6 +78,9 @@
if (firstToken.equalsIgnoreCase("delete")) { // //$NON-NLS-1$
String theDN = getDN(st); // the token after the marker is always DN
+ if (st.hasMoreTokens()) {
+ throw new TranslatorException(LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12013,
st.nextToken()));
+ }
try {
ldapCtx.destroySubcontext(theDN);
this.updateCount = 1;
@@ -86,7 +92,10 @@
}
else if (firstToken.equalsIgnoreCase("create")) { //$NON-NLS-1$
String theDN = getDN(st); // the token after the marker is always DN
- ArrayList<BasicAttribute> attributes = getAttributes(st, this.arguments);
+ ArrayList<BasicAttribute> attributes = getAttributes(st);
+ if (st.hasMoreTokens()) {
+ throw new TranslatorException(LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12013,
st.nextToken()));
+ }
BasicAttributes attrs = new BasicAttributes();
for (BasicAttribute ba:attributes) {
attrs.put(ba);
@@ -102,7 +111,10 @@
}
else if (firstToken.equalsIgnoreCase("update")) { //$NON-NLS-1$
String theDN = getDN(st); // the token after the marker is always DN
- ArrayList<BasicAttribute> attributes = getAttributes(st, this.arguments);
+ ArrayList<BasicAttribute> attributes = getAttributes(st);
+ if (st.hasMoreTokens()) {
+ throw new TranslatorException(LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12013,
st.nextToken()));
+ }
ModificationItem[] updateMods = new ModificationItem[attributes.size()];
int i=0;
for (BasicAttribute ba:attributes) {
@@ -117,7 +129,6 @@
throw new TranslatorException(e,
LDAPPlugin.Util.getString("LDAPUpdateExecution.updateFailedUnexpected",theDN));//$NON-NLS-1$
}
}
-
}
private String getDN(StringTokenizer st) throws TranslatorException {
@@ -127,26 +138,26 @@
return st.nextToken();
}
- private ArrayList<BasicAttribute> getAttributes(StringTokenizer st,
List<Argument> arguments) throws TranslatorException {
+ private ArrayList<BasicAttribute> getAttributes(StringTokenizer st) throws
TranslatorException {
if (!st.hasMoreTokens()) {
throw new TranslatorException(LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12011));
}
ArrayList<BasicAttribute> attributes = new ArrayList<BasicAttribute>();
- while(st.hasMoreElements()) {
+ if(st.hasMoreElements()) {
String var = st.nextToken();
int index = var.indexOf('=');
if (index == -1) {
- continue;
+ throw new TranslatorException(LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12011));
}
- String key = var.substring(0, index).trim().toLowerCase();
+ String key = var.substring(0, index).trim();
String value = var.substring(index+1).trim();
if (key.equalsIgnoreCase(ATTRIBUTES)) {
StringTokenizer attrTokens = new StringTokenizer(value, ",");
//$NON-NLS-1$
- int attrCount = 1;
+ int attrCount = 0;
while(attrTokens.hasMoreElements()) {
String name = attrTokens.nextToken().trim();
if (arguments.size() <= attrCount) {
@@ -156,7 +167,8 @@
Object anObj = argument.getArgumentValue().getValue();
attributes.add(new BasicAttribute(name, anObj));
}
-
+ } else {
+ throw new TranslatorException(LDAPPlugin.Util.gs(LDAPPlugin.Event.TEIID12011));
}
}
return attributes;
@@ -170,10 +182,12 @@
@Override
public List<?> next() throws TranslatorException, DataNotAvailableException {
if (this.updateCount != -1) {
- Object[] columns = new Object[1];
- columns[0] = this.updateCount;
- List<Object[]> row = new ArrayList<Object[]>(1);
- row.add(columns);
+ List<Object> row = Arrays.asList((Object)Integer.valueOf(this.updateCount));
+ if (returnsArray) {
+ Object[] columns = new Object[1];
+ columns[0] = this.updateCount;
+ row.set(0, columns);
+ }
this.updateCount = -1;
return row;
}
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-03
16:54:06 UTC (rev 4510)
+++
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPDirectSearchQueryExecution.java 2012-10-03
19:05:34 UTC (rev 4511)
@@ -28,6 +28,7 @@
import javax.naming.ldap.LdapContext;
import org.teiid.language.Argument;
+import org.teiid.language.visitor.SQLStringVisitor;
import org.teiid.translator.DataNotAvailableException;
import org.teiid.translator.ExecutionContext;
import org.teiid.translator.ProcedureExecution;
@@ -35,16 +36,26 @@
public class LDAPDirectSearchQueryExecution extends LDAPSyncQueryExecution implements
ProcedureExecution {
- private List<Argument> arguments;
+ private String query;
+ private boolean returnsArray = true;
- public LDAPDirectSearchQueryExecution(List<Argument> arguments,
LDAPExecutionFactory factory, ExecutionContext executionContext, LdapContext connection)
{
+ public LDAPDirectSearchQueryExecution(List<Argument> arguments,
LDAPExecutionFactory factory, ExecutionContext executionContext, LdapContext connection,
String query, boolean returnsArray) {
super(null, factory, executionContext, connection);
- this.arguments = arguments;
+ //perform substitution
+ StringBuilder sb = new StringBuilder();
+ SQLStringVisitor.parseNativeQueryParts(query.substring(7), arguments, sb, new
SQLStringVisitor.Substitutor() {
+
+ @Override
+ public void substitute(Argument arg, StringBuilder builder, int index) {
+ builder.append(IQueryToLdapSearchParser.escapeReservedChars(IQueryToLdapSearchParser.getExpressionString(arg.getArgumentValue())));
+ }
+ });
+ this.query = sb.toString();
+ this.returnsArray = returnsArray;
}
@Override
public void execute() 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.
@@ -67,9 +78,12 @@
if (vals == null) {
return null;
}
- List<Object[]> row = new ArrayList<Object[]>(1);
- row.add(vals.toArray(new Object[vals.size()]));
- return row;
+ if (returnsArray) {
+ List<Object[]> row = new ArrayList<Object[]>(1);
+ row.add(vals.toArray(new Object[vals.size()]));
+ return row;
+ }
+ return vals;
}
@Override
Modified:
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPExecutionFactory.java
===================================================================
---
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPExecutionFactory.java 2012-10-03
16:54:06 UTC (rev 4510)
+++
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPExecutionFactory.java 2012-10-03
19:05:34 UTC (rev 4511)
@@ -27,9 +27,11 @@
import javax.resource.cci.ConnectionFactory;
import org.teiid.language.Argument;
+import org.teiid.language.Call;
import org.teiid.language.Command;
import org.teiid.language.QueryExpression;
import org.teiid.language.Select;
+import org.teiid.language.visitor.SQLStringVisitor;
import org.teiid.metadata.RuntimeMetadata;
import org.teiid.translator.ExecutionContext;
import org.teiid.translator.ExecutionFactory;
@@ -108,12 +110,26 @@
public ProcedureExecution createDirectExecution(List<Argument> arguments,Command
command, ExecutionContext executionContext,RuntimeMetadata metadata, LdapContext context)
throws TranslatorException {
String query = (String) arguments.get(0).getArgumentValue().getValue();
if (query.startsWith("search;")) { //$NON-NLS-1$
- return new LDAPDirectSearchQueryExecution(arguments, this, executionContext,
context);
+ return new LDAPDirectSearchQueryExecution(arguments.subList(1, arguments.size()),
this, executionContext, context, query, true);
}
- return new LDAPDirectCreateUpdateDeleteQueryExecution(arguments, this,
executionContext, context);
+ return new LDAPDirectCreateUpdateDeleteQueryExecution(arguments.subList(1,
arguments.size()), this, executionContext, context, query, true);
}
@Override
+ public ProcedureExecution createProcedureExecution(Call command,
+ ExecutionContext executionContext, RuntimeMetadata metadata,
+ LdapContext connection) throws TranslatorException {
+ String nativeQuery =
command.getMetadataObject().getProperty(SQLStringVisitor.TEIID_NATIVE_QUERY, false);
+ if (nativeQuery != null) {
+ if (nativeQuery.startsWith("search;")) { //$NON-NLS-1$
+ return new LDAPDirectSearchQueryExecution(command.getArguments(), this,
executionContext, connection, nativeQuery, false);
+ }
+ return new LDAPDirectCreateUpdateDeleteQueryExecution(command.getArguments(), this,
executionContext, connection, nativeQuery, false);
+ }
+ throw new TranslatorException("Missing native-query extension metadata.");
//$NON-NLS-1$
+ }
+
+ @Override
public boolean supportsCompareCriteriaEquals() {
return true;
}
Modified:
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPPlugin.java
===================================================================
---
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPPlugin.java 2012-10-03
16:54:06 UTC (rev 4510)
+++
trunk/connectors/translator-ldap/src/main/java/org/teiid/translator/ldap/LDAPPlugin.java 2012-10-03
19:05:34 UTC (rev 4511)
@@ -39,17 +39,14 @@
public static final BundleUtil Util = new BundleUtil(PLUGIN_ID, PLUGIN_ID +
".i18n", ResourceBundle.getBundle(PLUGIN_ID + ".i18n")); //$NON-NLS-1$
//$NON-NLS-2$
public static enum Event implements BundleUtil.Event {
- TEIID12001, // unsupported capability
TEIID12002, // search failed
TEIID12003, // close context
TEIID12004, // attribute fetch error
- TEIID12005,
- TEIID12006,
- TEIID12007,
TEIID12008,
TEIID12009,
TEIID12010,
TEIID12011,
- TEIID12012,
+ TEIID12012,
+ TEIID12013,
}
}
Modified:
trunk/connectors/translator-ldap/src/main/resources/org/teiid/translator/ldap/i18n.properties
===================================================================
---
trunk/connectors/translator-ldap/src/main/resources/org/teiid/translator/ldap/i18n.properties 2012-10-03
16:54:06 UTC (rev 4510)
+++
trunk/connectors/translator-ldap/src/main/resources/org/teiid/translator/ldap/i18n.properties 2012-10-03
19:05:34 UTC (rev 4511)
@@ -25,8 +25,7 @@
IQueryToLdapSearchParser.baseContextNameError=Base context name (DN) not specified in
Name In Source or connector properties.
IQueryToLdapSearchParser.groupCountExceededError=Query contained from clause that did not
have exactly and only one group. Query not supported.
IQueryToLdapSearchParser.criteriaNotParsableError=Compound criteria operator was not
parsable.
-IQueryToLdapSearchParser.timestampClassNotFoundError=Timestamp class was not found.
-IQueryToLdapSearchParser.unsupportedElementError=Encountered an element type that is not
supported. Revise the capabilities.
+IQueryToLdapSearchParser.unsupportedElementError=Encountered an {0} that is not
supported. Revise the capabilities.
IQueryToLdapSearchParser.missingNISError=An element (or expression) found in the
query's compare criteria was missing a NameInSource definition (or name). Please
ensure the name in source is defined for each element.
IQueryToLdapSearchParser.criteriaNotSupportedError=Encountered a criteria that is not
supported.
IQueryToLdapSearchParser.searchDetailsLoggingError=Error writing LDAP search details to
log
@@ -62,13 +61,10 @@
ldap_error=Ldap error while processing next batch of results
-TEIID12001=Received IAggregate, but it is not supported. Check capabilities.
-TEIID12005=Received IFunction, but it is not supported. Check capabilties.
-TEIID12006=Received IScalarSubquery, but it is not supported. Check capabilties.
-TEIID12007=Received ISearchedCaseExpression, but it is not supported. Check capabilties.
TEIID12002=Attempted to search context: {0}
TEIID12008=LDAP Search results exceeded size limit. Results may be incomplete.
TEIID12009=Unknown LDAP Request; the query string must start with
[search|create|update|delete]
TEIID12010=The DN is not defined; DN should be the token after the marker tokens
[search|create|update|delete]
TEIID12011=attributes are not defined; use "attributes=..." form using the
comma delimited to specify all the names.
-TEIID12012=create/update operation did not find the value for attribute {0}; Each
attribute value is defined as the separate parameter in the procedure call.
\ No newline at end of file
+TEIID12012=create/update operation did not find the value for attribute {0}; Each
attribute value is defined as the separate parameter in the procedure call.
+TEIID12013=unknown option: {0}
\ No newline at end of file
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-03
16:54:06 UTC (rev 4510)
+++
trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestIQueryToLdapSearchParser.java 2012-10-03
19:05:34 UTC (rev 4511)
@@ -35,10 +35,10 @@
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.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;
@@ -246,25 +246,6 @@
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();
@@ -312,19 +293,6 @@
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);
}
Modified:
trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestLDAPDirectQueryExecution.java
===================================================================
---
trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestLDAPDirectQueryExecution.java 2012-10-03
16:54:06 UTC (rev 4510)
+++
trunk/connectors/translator-ldap/src/test/java/org/teiid/translator/ldap/TestLDAPDirectQueryExecution.java 2012-10-03
19:05:34 UTC (rev 4511)
@@ -21,8 +21,7 @@
*/
package org.teiid.translator.ldap;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.*;
import java.math.BigDecimal;
@@ -38,6 +37,7 @@
import org.teiid.cdk.unittest.FakeTranslationFactory;
import org.teiid.language.Command;
import org.teiid.metadata.RuntimeMetadata;
+import org.teiid.translator.Execution;
import org.teiid.translator.ExecutionContext;
import org.teiid.translator.TranslatorException;
@@ -54,7 +54,7 @@
}
@Test public void testSearch() throws Exception {
- String input = "exec
native('search;context-name=corporate;filter=(objectClass=*);count-limit=5;timout=6;search-scope=ONELEVEL_SCOPE;attributes=uid,cn')";
+ String input = "exec
native('search;context-name=corporate;filter=(objectClass=*);count-limit=5;timeout=6;search-scope=ONELEVEL_SCOPE;attributes=uid,cn')";
TranslationUtility util =
FakeTranslationFactory.getInstance().getExampleTranslationUtility();
Command command = util.parseCommand(input);
@@ -71,13 +71,37 @@
assertEquals("corporate", details.getContextName());
assertEquals("(objectClass=*)", details.getContextFilter());
assertEquals(5, details.getCountLimit());
+ assertEquals(6, details.getTimeLimit());
assertEquals(1, details.getSearchScope());
assertEquals(2, details.getElementList().size());
assertEquals("uid", details.getElementList().get(0).getName());
assertEquals("cn", details.getElementList().get(1).getName());
- }
+ }
- @Test public void testWithoutMarker() throws Exception {
+ @Test public void testSearchDefaultsAndEscaping() throws Exception {
+ String input = "exec
native('search;context-name=corporate;filter=(;;)')";
+
+ TranslationUtility util =
FakeTranslationFactory.getInstance().getExampleTranslationUtility();
+ Command command = util.parseCommand(input);
+ ExecutionContext ec = Mockito.mock(ExecutionContext.class);
+ RuntimeMetadata rm = Mockito.mock(RuntimeMetadata.class);
+ LdapContext connection = Mockito.mock(LdapContext.class);
+ LdapContext ctx = Mockito.mock(LdapContext.class);
+ Mockito.stub(connection.lookup("corporate")).toReturn(ctx);
+
+ LDAPDirectSearchQueryExecution execution =
(LDAPDirectSearchQueryExecution)TRANSLATOR.createExecution(command, ec, rm, connection);
+ execution.execute();
+ LDAPSearchDetails details = execution.getDelegate().getSearchDetails();
+
+ assertEquals("corporate", details.getContextName());
+ assertEquals("(;)", details.getContextFilter());
+ assertEquals(-1, details.getCountLimit());
+ assertEquals(0, details.getTimeLimit());
+ assertEquals(1, details.getSearchScope());
+ assertEquals(0, details.getElementList().size());
+ }
+
+ @Test(expected=TranslatorException.class) public void testWithoutMarker() throws
Exception {
String input = "exec
native('context-name=corporate;filter=(objectClass=*);count-limit=5;timout=6;search-scope=ONELEVEL_SCOPE;attributes=uid,cn')";
TranslationUtility util =
FakeTranslationFactory.getInstance().getExampleTranslationUtility();
@@ -88,12 +112,9 @@
LdapContext ctx = Mockito.mock(LdapContext.class);
Mockito.stub(connection.lookup("corporate")).toReturn(ctx);
- try {
- LDAPDirectSearchQueryExecution execution =
(LDAPDirectSearchQueryExecution)TRANSLATOR.createExecution(command, ec, rm, connection);
- execution.execute();
- fail("the above should have thrown exception");
- } catch (ClassCastException e) {
- }
+ Execution execution = TRANSLATOR.createExecution(command, ec, rm, connection);
+ assertTrue(!(execution instanceof LDAPDirectSearchQueryExecution));
+ execution.execute();
}
@Test public void testDelete() throws Exception {
@@ -167,7 +188,7 @@
assertEquals(new BigDecimal("3.0"),
createItemArgument.getValue().get("three").get());
}
- @Test public void testCreateFail() throws Exception {
+ @Test(expected=TranslatorException.class) public void testCreateFail() throws
Exception {
String input = "exec
native('create;uid=doe,ou=people,o=teiid.org;attributes=one,two,three',
'one')";
TranslationUtility util =
FakeTranslationFactory.getInstance().getExampleTranslationUtility();
@@ -178,11 +199,7 @@
LdapContext ctx = Mockito.mock(LdapContext.class);
Mockito.stub(connection.lookup("")).toReturn(ctx);
- try {
- LDAPDirectCreateUpdateDeleteQueryExecution execution =
(LDAPDirectCreateUpdateDeleteQueryExecution)TRANSLATOR.createExecution(command, ec, rm,
connection);
- execution.execute();
- fail("should have failed because there are not enough values");
- } catch (TranslatorException e) {
- }
+ LDAPDirectCreateUpdateDeleteQueryExecution execution =
(LDAPDirectCreateUpdateDeleteQueryExecution)TRANSLATOR.createExecution(command, ec, rm,
connection);
+ execution.execute();
}
}