From 6a76f80824cb0a6b3671d4051982ec06f63e91ce Mon Sep 17 00:00:00 2001
From: Glenn Van Lint <glenn.vanlint@is4u.be>
Date: Tue, 21 May 2013 22:58:38 +0000
Subject: [PATCH] Fixed bug in ConvertSearchFilter() when there was only 1 subfilter present. Added documentation.
---
opendj-sdk/opendj3/opendj-virtual/src/main/java/org/forgerock/opendj/virtual/JDBCConnection.java | 681 +++++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 522 insertions(+), 159 deletions(-)
diff --git a/opendj-sdk/opendj3/opendj-virtual/src/main/java/org/forgerock/opendj/virtual/JDBCConnection.java b/opendj-sdk/opendj3/opendj-virtual/src/main/java/org/forgerock/opendj/virtual/JDBCConnection.java
index 00d7134..3d26b0a 100644
--- a/opendj-sdk/opendj3/opendj-virtual/src/main/java/org/forgerock/opendj/virtual/JDBCConnection.java
+++ b/opendj-sdk/opendj3/opendj-virtual/src/main/java/org/forgerock/opendj/virtual/JDBCConnection.java
@@ -65,8 +65,11 @@
import org.forgerock.opendj.ldap.responses.Responses;
import org.forgerock.opendj.ldap.responses.Result;
+/**
+ * JDBC connection implementation.
+ */
public final class JDBCConnection extends AbstractSynchronousConnection {
- // For connection to h2 database, use driverName = "org.h2.driver";
+ //For connection to h2 database, use driverName = "org.h2.driver";
private final String driverName = "com.mysql.jdbc.Driver";
private java.sql.Connection connection;
private String connectionUrl;
@@ -74,88 +77,139 @@
private MappingConfigurationManager mcm;
private List<Entry> searchEntries = new ArrayList<Entry>();
+ /**
+ * Creates a new JDBC connection.
+ *
+ * @param connectionURL
+ * The URL to connect to the SQL Database Server consisting of the
+ * host name, port number and name of the database.
+ */
JDBCConnection(final String connectionURL)
{
this.connectionUrl = connectionURL;
}
- public void initializeMapper(JDBCMapper jdbcmapper) throws SQLException, ErrorResultException, IOException
+ /**
+ * Initializes the mapping component for this connection.
+ *
+ * @param jdbcMapper
+ * The JDBCMapper object used to map the directory and database
+ * structure.
+ */
+ public void initializeMapper(final JDBCMapper jdbcMapper) throws SQLException, ErrorResultException, IOException
{
- jdbcm = jdbcmapper;
+ //Load the jdbc mapper with the mapping from the properties file using the Mapping Configuration Manager.
+ jdbcm = jdbcMapper;
jdbcm.fillMaps();
mcm = new MappingConfigurationManager(jdbcm);
jdbcm.loadMappingConfig(mcm.loadMapping());
}
+ /**
+ * Returns the SQL connection used by the SQL driver to connect with the database.
+ *
+ * @return A connection to the database used by the SQL driver.
+ */
public java.sql.Connection getSqlConnection()
{
return connection;
}
+ /**
+ * Adds a record to the Database Server using the provided add request.
+ *
+ * @param request
+ * The add request.
+ * @return The result of the operation.
+ * @throws ErrorResultException
+ * If the result code indicates that the request failed for some
+ * reason.
+ * @throws SQLException
+ * If the SQL query has an invalid format.
+ * @throws NullPointerException
+ * If {@code request} was {@code null}, or if
+ * a corresponding mapping value could not be found in the mapping component.
+ */
@Override
- public Result add(AddRequest request) throws ErrorResultException
+ public Result add(final AddRequest request) throws ErrorResultException
{
Result r;
try {
+ //Split up the DN the of the request.
final DN DN = request.getName();
+ final RDN rDN = DN.rdn();
+ final String rDNName = rDN.getFirstAVA().getAttributeType().getNameOrOID();
+ final String rDNValue = rDN.getFirstAVA().getAttributeValue().toString();
final RDN OU = DN.parent().rdn();
final String organizationalUnitName = OU.getFirstAVA().getAttributeValue().toString();
final String baseDN = DN.parent(2).toString();
+
+ //Search mapping for the corresponding table and column names.
final String tableName = jdbcm.getTableNameFromMapping(baseDN, organizationalUnitName);
+
+ if(tableName == null) throw new NullPointerException("JDBC Error: Could not find matching table name for OU: '" + organizationalUnitName + "' in DN: '" + baseDN + "'. Please check if mapping was succesful.");
+ final String rDNColumnName = jdbcm.getColumnNameFromMapping(tableName, baseDN, organizationalUnitName, rDNName);
+
+ if(rDNColumnName == null) throw new NullPointerException("JDBC Error: Could not find matching column name for attribute: '" + rDNName + "'. Please check if mapping was succesful.");
final Map<String, Object> columnValuesMap = new HashMap<String, Object>();
final Iterable<Attribute> attributesCollection = request.getAllAttributes();
final Iterator<Attribute> attributeIter = attributesCollection.iterator();
+ //Search mapping for the corresponding column name for each attribute.
while(attributeIter.hasNext()){
final Attribute att = attributeIter.next();
final Iterator<ByteString> valueIter = att.iterator();
final String attributeName = att.getAttributeDescriptionAsString();
- final String columnName = jdbcm.getColumnNameFromMapping(tableName, baseDN, organizationalUnitName, attributeName);
- String columnValue = "";
- if (columnName == null) continue;
+ if(attributeName == "objectClass") continue;
+ final String columnName = jdbcm.getColumnNameFromMapping(tableName, baseDN, organizationalUnitName, attributeName);
+
+ if(columnName == null) throw new NullPointerException("JDBC Error: Could not find matching column name for attribute: '" + attributeName + "'. Please check if mapping was succesful.");
+ String columnValue = "";
while(valueIter.hasNext()){
columnValue = columnValue.concat(valueIter.next().toString());
}
columnValuesMap.put(columnName, columnValue);
}
+
+ //Build the SQL values String.
final ArrayList<String>columnList = jdbcm.getTableColumns(tableName);
- String columnNamesString = " (";
- String columnValuesString = " (";
+ String columnNamesString = " (" + rDNColumnName;
+ String columnValuesString = " ('" + rDNValue + "'";
for(int i = 0; i < columnList.size(); i++){
-
- if (i > 0){
- columnNamesString = columnNamesString.concat(", ");
- columnValuesString = columnValuesString.concat(", ");
- }
final String columnName = columnList.get(i);
+
+ if(columnNamesString.contains(columnName)) continue;
final Object columnDataType = jdbcm.getTableColumnDataType(tableName, columnName);
Object columnValue = columnValuesMap.get(columnName);
if(columnValue == null){
-
if(columnDataType.equals(Integer.class)) columnValue = "0";
else columnValue = "Default Value";
}
if(columnDataType.equals(Integer.class)) columnValue = Integer.parseInt(columnValue.toString());
-
- columnNamesString = columnNamesString.concat(columnName);
- columnValuesString = columnValuesString.concat("'" + columnValue + "'");
+ columnNamesString = columnNamesString.concat(", " + columnName);
+ columnValuesString = columnValuesString.concat(", '" + columnValue + "'");
}
columnNamesString = columnNamesString.concat(")");
columnValuesString = columnValuesString.concat(")");
+ //Build the SQL query.
final Statement st = connection.createStatement();
final String sql = "INSERT INTO " + tableName + columnNamesString + " VALUES" + columnValuesString;
st.executeUpdate(sql);
r = Responses.newResult(ResultCode.SUCCESS);
-
- } catch (SQLException e) {
+ }catch (SQLException e) {
System.out.println(e.toString());
r = Responses.newResult(ResultCode.OPERATIONS_ERROR);
+ r.setCause(e);
+ }catch (NullPointerException e){
+ System.out.println(e.toString());
+ r = Responses.newResult(ResultCode.OPERATIONS_ERROR);
+ r.setCause(e);
}
return r;
}
@@ -166,10 +220,27 @@
// TODO Auto-generated method stub
}
+ /**
+ * Authenticates to the Database Server using the provided bind request.
+ *
+ * @param request
+ * The bind request.
+ * @return The result of the operation.
+ * @throws ErrorResultException
+ * If the result code indicates that the request failed for some
+ * reason.
+ * @throws ClassNotFoundException
+ * If no definition for the class with the specified driver name could be found.
+ * @throws SQLException
+ * If the driver could not establish a connection with the
+ * Database Server.
+ */
@Override
- public BindResult bind(BindRequest request) throws ErrorResultException
+ public BindResult bind(final BindRequest request) throws ErrorResultException
{
BindResult r;
+
+ //Extract user name and password from the bind request.
final String userName = request.getName();
final String userPass;
byte[] password = null;
@@ -182,15 +253,16 @@
}
userPass = new String(password);
+ //Establish SQL connection to the Database Server.
try {
Class.forName(driverName);
this.connection = DriverManager
.getConnection(this.connectionUrl,userName , userPass);
- } catch (ClassNotFoundException e) {
+ }catch (ClassNotFoundException e) {
System.out.println(e.toString());
r = Responses.newBindResult(ResultCode.OTHER);
return r;
- } catch (SQLException e) {
+ }catch (SQLException e) {
System.out.println(e.toString());
r = Responses.newBindResult(ResultCode.CLIENT_SIDE_CONNECT_ERROR);
return r;
@@ -199,8 +271,11 @@
return r;
}
+ /**
+ * {@inheritDoc}
+ */
@Override
- public void close(UnbindRequest request, String reason)
+ public void close(final UnbindRequest request, final String reason)
{
if(connection != null){
try
@@ -214,12 +289,28 @@
}
}
+ /**
+ * Compares a record in the Database Server using the provided compare request.
+ *
+ * @param request
+ * The compare request.
+ * @return The result of the operation.
+ * @throws ErrorResultException
+ * If the result code indicates that the request failed for some
+ * reason.
+ * @throws SQLException
+ * If the SQL query has an invalid format.
+ * @throws NullPointerException
+ * If {@code request} was {@code null}, or if
+ * a corresponding mapping value could not be found in the mapping component.
+ */
@Override
- public CompareResult compare(CompareRequest request) throws ErrorResultException
+ public CompareResult compare(final CompareRequest request) throws ErrorResultException
{
CompareResult cr;
try
{
+ //Split up the DN the of the request.
final DN DN = request.getName();
final RDN rDN = DN.rdn();
final String filterAttributeName = rDN.getFirstAVA().getAttributeType().getNameOrOID();
@@ -227,31 +318,61 @@
final RDN OU = DN.parent(1).rdn();
final String OUName = OU.getFirstAVA().getAttributeValue().toString();
final String baseDN = DN.parent(2).toString();
+
+ //Search mapping for the corresponding table and column names.
final String tableName = jdbcm.getTableNameFromMapping(baseDN, OUName);
+
+ if(tableName == null) throw new NullPointerException("JDBC Error: Could not find matching table name for OU: '" + OUName + "' in DN: '" + baseDN + "'. Please check if mapping was succesful.");
final String columnName = jdbcm.getColumnNameFromMapping(tableName, baseDN, OUName, filterAttributeName);
+
+ if(columnName == null) throw new NullPointerException("JDBC Error: Could not find matching column name for attribute: '" + filterAttributeName + "'. Please check if mapping was succesful.");
+
+ //Search mapping for the corresponding column name for the comparing attribute.
final String compareAttributeName = request.getAttributeDescription().toString();
final String compareAttributeValue = request.getAssertionValueAsString();
final String compareColumnName = jdbcm.getColumnNameFromMapping(tableName, baseDN, OUName, compareAttributeName);
+ if(compareColumnName == null) throw new NullPointerException("JDBC Error: Could not find matching column name for attribute: '" + compareAttributeName + "'. Please check if mapping was succesful.");
+
+ //Build the SQL query.
final Statement st = connection.createStatement();
final String sql = "SELECT * FROM " + tableName + " WHERE " + columnName + "='" + filterAttributeValue + "' AND " + compareColumnName + "='" + compareAttributeValue + "'";
final ResultSet rs = st.executeQuery(sql);
if(rs.first()) cr = Responses.newCompareResult(ResultCode.COMPARE_TRUE);
else cr = Responses.newCompareResult(ResultCode.COMPARE_FALSE);
- }
- catch (SQLException e)
- {
+ }catch (SQLException e) {
+ System.out.println(e.toString());
cr = Responses.newCompareResult(ResultCode.OPERATIONS_ERROR);
- e.printStackTrace();
+ cr.setCause(e);
+ }catch (NullPointerException e){
+ System.out.println(e.toString());
+ cr = Responses.newCompareResult(ResultCode.OPERATIONS_ERROR);
+ cr.setCause(e);
}
return cr;
}
+ /**
+ * Deletes a record from the Database Server using the provided delete request.
+ *
+ * @param request
+ * The delete request.
+ * @return The result of the operation.
+ * @throws ErrorResultException
+ * If the result code indicates that the request failed for some
+ * reason.
+ * @throws SQLException
+ * If the SQL query has an invalid format.
+ * @throws NullPointerException
+ * If {@code request} was {@code null}, or if
+ * a corresponding mapping value could not be found in the mapping component.
+ */
@Override
public Result delete(DeleteRequest request) throws ErrorResultException
{
Result r;
try{
+ //Split up the DN the of the request.
final DN DN = request.getName();
final RDN rDN = DN.rdn();
final String filterAttributeName = rDN.getFirstAVA().getAttributeType().getNameOrOID();
@@ -259,16 +380,28 @@
final RDN OU = DN.parent(1).rdn();
final String OUName = OU.getFirstAVA().getAttributeValue().toString();
final String baseDN = DN.parent(2).toString();
+
+ //Search mapping for the corresponding table and column names.
final String tableName = jdbcm.getTableNameFromMapping(baseDN, OUName);
+
+ if(tableName == null) throw new NullPointerException("JDBC Error: Could not find matching table name for OU: '" + OUName + "' in DN: '" + baseDN + "'. Please check if mapping was succesful.");
final String columnName = jdbcm.getColumnNameFromMapping(tableName, baseDN, OUName, filterAttributeName);
+ if(columnName == null) throw new NullPointerException("JDBC Error: Could not find matching column name for attribute: '" + filterAttributeName + "'. Please check if mapping was succesful.");
+
+ //Build the SQL query.
final Statement st = connection.createStatement();
final String sql = "DELETE FROM " + tableName + " WHERE " + columnName + "='" + filterAttributeValue + "'";
st.executeUpdate(sql);
r = Responses.newResult(ResultCode.SUCCESS);
- } catch (SQLException e) {
+ }catch (SQLException e) {
System.out.println(e.toString());
r = Responses.newResult(ResultCode.OPERATIONS_ERROR);
+ r.setCause(e);
+ }catch (NullPointerException e){
+ System.out.println(e.toString());
+ r = Responses.newCompareResult(ResultCode.OPERATIONS_ERROR);
+ r.setCause(e);
}
return r;
}
@@ -282,6 +415,9 @@
return null;
}
+ /**
+ * {@inheritDoc}
+ */
@Override
public boolean isClosed()
{
@@ -296,6 +432,9 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
@Override
public boolean isValid()
{
@@ -310,11 +449,27 @@
}
}
+ /**
+ * Modifies a record in the Database Server using the provided modify request.
+ *
+ * @param request
+ * The modify request.
+ * @return The result of the operation.
+ * @throws ErrorResultException
+ * If the result code indicates that the request failed for some
+ * reason.
+ * @throws SQLException
+ * If the SQL query has an invalid format.
+ * @throws NullPointerException
+ * If {@code request} was {@code null}, or if
+ * a corresponding mapping value could not be found in the mapping component.
+ */
@Override
- public Result modify(ModifyRequest request)
+ public Result modify(final ModifyRequest request)
{
Result r;
try{
+ //Split up the DN the of the request.
final DN DN = request.getName();
final RDN rDN = DN.rdn();
final String filterAttributeName = rDN.getFirstAVA().getAttributeType().getNameOrOID();
@@ -322,8 +477,17 @@
final RDN OU = DN.parent(1).rdn();
final String OUName = OU.getFirstAVA().getAttributeValue().toString();
final String baseDN = DN.parent(2).toString();
+
+ //Search mapping for the corresponding table and column names.
final String tableName = jdbcm.getTableNameFromMapping(baseDN, OUName);
+
+ if(tableName == null) throw new NullPointerException("JDBC Error: Could not find matching table name for OU: '" + OUName + "' in DN: '" + baseDN + "'. Please check if mapping was succesful.");
final String columnName = jdbcm.getColumnNameFromMapping(tableName, baseDN, OUName, filterAttributeName);
+
+ if(columnName == null) throw new NullPointerException("JDBC Error: Could not find matching column name for attribute: '" + filterAttributeName + "'. Please check if mapping was succesful.");
+
+ //Get attribute and modificationtype for each modification.
+ //Search mapping for the corresponding column name for the modification attribute.
final List<Modification> modificationList = request.getModifications();
final ListIterator<Modification> listIter = modificationList.listIterator();
String modificationString = "";
@@ -334,6 +498,8 @@
final Attribute modificationAttribute = modification.getAttribute();
final String modificationAttributeName = modificationAttribute.getAttributeDescription().toString();
final String modificationColumnName = jdbcm.getColumnNameFromMapping(tableName, baseDN, OUName, modificationAttributeName);
+
+ if(modificationColumnName == null) throw new NullPointerException("JDBC Error: Could not find matching column name for attribute: '" + modificationAttributeName + "'. Please check if mapping was succesful.");
String modificationAttributeValue = "";
if(modificationType == ModificationType.ADD){
@@ -346,10 +512,11 @@
counter++;
}
final Object classType = jdbcm.getTableColumnDataType(tableName, modificationColumnName);
- if(classType == Integer.class) modificationAttributeValue = "(case when (" + modificationAttributeName + " = 0) THEN ' "
- + modificationAttributeValue + "' ELSE concat(" + modificationAttributeName + ", ', " + modificationAttributeValue + "') END)";
- else modificationAttributeValue = "(case when (" + modificationAttributeName + " = 'Default Value') THEN ' "
- + modificationAttributeValue + "' ELSE concat(" + modificationAttributeName + ", ', " + modificationAttributeValue + "') END)";
+
+ if(classType == Integer.class) modificationAttributeValue = "(CASE WHEN (" + modificationColumnName + " = 0) THEN ' "
+ + modificationAttributeValue + "' ELSE concat(" + modificationColumnName + ", ', " + modificationAttributeValue + "') END)";
+ else modificationAttributeValue = "(CASE WHEN (" + modificationColumnName + " = 'Default Value') THEN ' "
+ + modificationAttributeValue + "' ELSE concat(" + modificationColumnName + ", ', " + modificationAttributeValue + "') END)";
}
else if(modificationType == ModificationType.REPLACE){
final Iterator<ByteString> iter = modificationAttribute.iterator();
@@ -370,14 +537,20 @@
modificationString = modificationString.concat(modificationColumnName + "=" + modificationAttributeValue + ", ");
}
modificationString = modificationString.substring(0, modificationString.length() - 2);
- final String sql = "UPDATE " + tableName + " SET " + modificationString + " WHERE " + columnName + "='" + filterAttributeValue + "'";
+ //Build the SQL query.
final Statement st = connection.createStatement();
+ final String sql = "UPDATE " + tableName + " SET " + modificationString + " WHERE " + columnName + "='" + filterAttributeValue + "'";
st.executeUpdate(sql);
r = Responses.newResult(ResultCode.SUCCESS);
- }catch (SQLException e){
+ }catch (SQLException e) {
System.out.println(e.toString());
r = Responses.newResult(ResultCode.OPERATIONS_ERROR);
+ r.setCause(e);
+ }catch (NullPointerException e){
+ System.out.println(e.toString());
+ r = Responses.newCompareResult(ResultCode.OPERATIONS_ERROR);
+ r.setCause(e);
}
return r;
}
@@ -395,123 +568,92 @@
// TODO Auto-generated method stub
}
+ /**
+ * Converts the LDAP filter to an SQL filter.
+ *
+ * @param filter
+ * The filter of the search request.
+ * @param baseDN
+ * The top domain name.
+ * @param OUName
+ * The name of the organizational unit.
+ * @return The converted SQL filter.
+ * @throws NullPointerException
+ * If the result code indicates that the request failed for some
+ * reason.
+ * @throws SQLException
+ * If the SQL query has an invalid format.
+ * @throws NullPointerException
+ * If {@code filter}, {@code baseDN} or {@code OUName} was {@code null}, or if
+ * a corresponding mapping value could not be found in the mapping component.
+ */
private String convertSearchFilter(final Filter filter, final String baseDN, String OUName)
{
- String filterString = filter.toString();
- int stringIndex = 0;
- int subStringCount = 0;
+ try{
+ String filterString = filter.toString();
+ String convertedFilterString = "";
- while(filterString.charAt(stringIndex) == '('){
- if(filterString.charAt(stringIndex + 2) == '('){
- subStringCount++;
- }
- stringIndex += 2;
- }
- int subStringStartIndex = 2 * subStringCount;
- int subStringEndIndex = 0;
- final String[] subStrings = new String[subStringCount];
- final char[] operationChars = new char[subStringCount];
+ if(filterString.isEmpty() || filterString.contains("objectClass=*")) return "";
+ int stringIndex = 0;
+ int subStringCount = 0;
- while(subStringStartIndex > 0){
- final char operationChar = filterString.charAt(subStringStartIndex - 1);
- subStringEndIndex = filterString.indexOf("))") + 1;
- String subString = filterString.substring(subStringStartIndex, subStringEndIndex);
- subString = subString.replace("()","");
- operationChars[subStringCount - subStringStartIndex / 2] = operationChar;
- subStrings[subStringCount - subStringStartIndex / 2] = subString;
-
- final String replaceString = filterString.substring(subStringStartIndex - 1, subStringEndIndex);
- filterString = filterString.replace(replaceString, "");
-
- subStringStartIndex-=2;
- }
- String convertedFilterString = "";
-
- for(int i = 0; i < subStringCount; i++){
- final char operationChar = operationChars[i];
-
- if(operationChar == '!'){
- String subString = subStrings[i];
-
- if(subString.isEmpty()){
- subString = subStrings[i-1];
- subString = subString.replace(">=", ">");
- subString = subString.replace("<=", "<");
- subString = subString.replace("=", "!=");
- subString = subString.replace(">", ">=");
- subString = subString.replace("<", "<=");
- subStrings[i-1] = subString;
+ //Set the amount of subfilters if operators are present.
+ while(filterString.charAt(stringIndex) == '('){
+ if(filterString.charAt(stringIndex + 2) == '('){
+ subStringCount++;
}
- else{
- subString = subString.replace(">=", ">");
- subString = subString.replace("<=", "<");
- subString = subString.replace("=", "!=");
- subString = subString.replace(">", ">=");
- subString = subString.replace("<", "<=");
- subStrings[i] = subString;
- }
- }
- }
- boolean multipleSubStrings = false;
-
- if(subStringCount > 1) multipleSubStrings = true;
-
- for(int i = 0; i < subStringCount; i++){
- final char operationChar = operationChars[i];
- String operationString = "";
-
- if(operationChar == '&'){
- operationString = " AND ";
- }
- else if (operationChar == '|'){
- operationString = " OR ";
+ stringIndex += 2;
}
- String subString = subStrings[i];
- if (subString.isEmpty()) continue;
+ if(subStringCount == 0){
+ //Replace escape characters.
+ String subString = filterString.substring(1, filterString.length()-1);
+ subString = subString.replace("\\02a", "*");
+ subString = subString.replace("\\028", "(");
+ subString = subString.replace("\\029", ")");
- subString = subString.substring(1, subString.length() - 1);
- String[] subStringSplitter = subString.split("\\)\\(");
+ String[] subStringSplitter;
- for(int j = 0; j < subStringSplitter.length; j++){
- String subStringFilter = subStringSplitter[j];
- final String[] subStringFilterSplitter;
+ if(subString.contains("<=")) subStringSplitter = subString.split("<=");
+ else if(subString.contains(">=")) subStringSplitter = subString.split(">=");
+ else subStringSplitter = subString.split("=");
- subStringFilter = subStringFilter.replace("\\02a", "*");
- subStringFilter = subStringFilter.replace("\\028", "(");
- subStringFilter = subStringFilter.replace("\\029", ")");
-
- if(subStringFilter.contains("!=")) subStringFilterSplitter = subStringFilter.split("!=");
- else if(subStringFilter.contains("<=")) subStringFilterSplitter = subStringFilter.split("<=");
- else if(subStringFilter.contains(">=")) subStringFilterSplitter = subStringFilter.split(">=");
- else subStringFilterSplitter = subStringFilter.split("=");
-
- final String filterAttributeName = subStringFilterSplitter[0];
+ final String filterAttributeName = subStringSplitter[0];
String filterColumnName = null;;
Object columnDataType = null;
- if(OUName == null){
+ //Search mapping for the corresponding table and column names.
+ if(OUName.isEmpty()){
final List<String> OUList = jdbcm.getOrganizationalUnits(baseDN);
for(Iterator<String> iter = OUList.iterator(); iter.hasNext();){
OUName = iter.next();
final String tableName = jdbcm.getTableNameFromMapping(baseDN, OUName);
+
+ if(tableName == null) continue;
filterColumnName = jdbcm.getColumnNameFromMapping(tableName, baseDN, OUName, filterAttributeName);
if(filterColumnName == null) continue;
else columnDataType = jdbcm.getTableColumnDataType(tableName, filterColumnName);
break;
}
+
+ if(filterColumnName == null) throw new NullPointerException("JDBC Error: Could not find matching column name for attribute: '" + filterAttributeName + "'. Please check if mapping was succesful.");
}
else{
final String tableName = jdbcm.getTableNameFromMapping(baseDN, OUName);
- filterColumnName = jdbcm.getColumnNameFromMapping(tableName, baseDN, OUName, filterAttributeName);
+
+ if(tableName == null) throw new NullPointerException("JDBC Error: Could not find matching table name for OU: '" + OUName + "' in DN: '" + baseDN + "'. Please check if mapping was succesful.");
+ filterColumnName = jdbcm.getColumnNameFromMapping(tableName, baseDN, OUName, filterAttributeName);
+
+ if(filterColumnName == null) throw new NullPointerException("JDBC Error: Could not find matching column name for attribute: '" + filterAttributeName + "'. Please check if mapping was succesful.");
columnDataType = jdbcm.getTableColumnDataType(tableName, filterColumnName);
}
+ //Set values to right format.
if(columnDataType != Integer.class){
- String filterAttributeValue = subStringFilterSplitter[1];
+ String filterAttributeValue = subStringSplitter[1];
String filterColumnValue = "'" + filterAttributeValue + "'";
filterAttributeValue = filterAttributeValue.replace("*", "\\*");
filterAttributeValue = filterAttributeValue.replace("(", "\\(");
@@ -520,34 +662,194 @@
if(filterColumnValue.length() > 3 && filterColumnValue.contains("*")){
filterColumnValue = filterColumnValue.replace("*", "%");
- if(subStringFilter.contains("!=")) subStringFilter = subStringFilter.replace("!=", " not like ");
- else subStringFilter = subStringFilter.replace("=", " like ");
+ subString = subString.replace("=", " like ");
}
- subStringFilter = subStringFilter.replaceFirst(filterAttributeValue, filterColumnValue);
+ subString = subString.replaceFirst(filterAttributeValue, filterColumnValue);
+ }
+ subString = subString.replaceFirst(filterAttributeName, filterColumnName);
+ convertedFilterString = convertedFilterString.concat(subString);
+ }
+ else
+ {
+ int subStringStartIndex = 2 * subStringCount;
+ int subStringEndIndex = 0;
+ final String[] subStrings = new String[subStringCount];
+ final char[] operationChars = new char[subStringCount];
+
+ //Separate operation characters and subfilters.
+ while(subStringStartIndex > 0){
+ final char operationChar = filterString.charAt(subStringStartIndex - 1);
+ subStringEndIndex = filterString.indexOf("))") + 1;
+ String subString = filterString.substring(subStringStartIndex, subStringEndIndex);
+ subString = subString.replace("()","");
+
+ operationChars[subStringCount - subStringStartIndex / 2] = operationChar;
+ subStrings[subStringCount - subStringStartIndex / 2] = subString;
+
+ final String replaceString = filterString.substring(subStringStartIndex - 1, subStringEndIndex);
+ filterString = filterString.replace(replaceString, "");
+
+ subStringStartIndex-=2;
}
- if(filterColumnName == null) continue;
- subStringFilter = subStringFilter.replaceFirst(filterAttributeName, filterColumnName);
+ //Handle the not operator.
+ for(int i = 0; i < subStringCount; i++){
+ final char operationChar = operationChars[i];
- if(j != 0 || i != 0) convertedFilterString = convertedFilterString.concat(operationString);
- convertedFilterString = convertedFilterString.concat(subStringFilter);
+ if(operationChar == '!'){
+ String subString = subStrings[i];
+
+ if(subString.isEmpty()){
+ subString = subStrings[i-1];
+ subString = subString.replace(">=", ">");
+ subString = subString.replace("<=", "<");
+ subString = subString.replace("=", "!=");
+ subString = subString.replace(">", ">=");
+ subString = subString.replace("<", "<=");
+ subStrings[i-1] = subString;
+ }
+ else{
+ subString = subString.replace(">=", ">");
+ subString = subString.replace("<=", "<");
+ subString = subString.replace("=", "!=");
+ subString = subString.replace(">", ">=");
+ subString = subString.replace("<", "<=");
+ subStrings[i] = subString;
+ }
+ }
+ }
+ boolean multipleSubStrings = false;
+
+ if(subStringCount > 1) multipleSubStrings = true;
+
+ //Convert each subfilter with corresponding operator.
+ for(int i = 0; i < subStringCount; i++){
+ final char operationChar = operationChars[i];
+ String operationString = "";
+
+ if(operationChar == '&'){
+ operationString = " AND ";
+ }
+ else if (operationChar == '|'){
+ operationString = " OR ";
+ }
+
+ String subString = subStrings[i];
+ if (subString.isEmpty()) continue;
+
+ subString = subString.substring(1, subString.length() - 1);
+ String[] subStringSplitter = subString.split("\\)\\(");
+
+ for(int j = 0; j < subStringSplitter.length; j++){
+ String subStringFilter = subStringSplitter[j];
+ final String[] subStringFilterSplitter;
+
+ subStringFilter = subStringFilter.replace("\\02a", "*");
+ subStringFilter = subStringFilter.replace("\\028", "(");
+ subStringFilter = subStringFilter.replace("\\029", ")");
+
+ if(subStringFilter.contains("!=")) subStringFilterSplitter = subStringFilter.split("!=");
+ else if(subStringFilter.contains("<=")) subStringFilterSplitter = subStringFilter.split("<=");
+ else if(subStringFilter.contains(">=")) subStringFilterSplitter = subStringFilter.split(">=");
+ else subStringFilterSplitter = subStringFilter.split("=");
+
+ final String filterAttributeName = subStringFilterSplitter[0];
+ String filterColumnName = null;;
+ Object columnDataType = null;
+
+ //Search mapping for the corresponding column name for each filter attribute.
+ if(OUName.isEmpty()){
+ final List<String> OUList = jdbcm.getOrganizationalUnits(baseDN);
+
+ for(Iterator<String> iter = OUList.iterator(); iter.hasNext();){
+ OUName = iter.next();
+ final String tableName = jdbcm.getTableNameFromMapping(baseDN, OUName);
+
+ if(tableName == null) continue;
+ filterColumnName = jdbcm.getColumnNameFromMapping(tableName, baseDN, OUName, filterAttributeName);
+
+ if(filterColumnName == null) continue;
+ else columnDataType = jdbcm.getTableColumnDataType(tableName, filterColumnName);
+ break;
+ }
+ if(filterColumnName == null) throw new NullPointerException("JDBC Error: Could not find matching column name for attribute: '" + filterAttributeName + "'. Please check if mapping was succesful.");
+ }
+ else{
+ final String tableName = jdbcm.getTableNameFromMapping(baseDN, OUName);
+
+ if(tableName == null) throw new NullPointerException("JDBC Error: Could not find matching table name for OU: '" + OUName + "' in DN: '" + baseDN + "'. Please check if mapping was succesful.");
+ filterColumnName = jdbcm.getColumnNameFromMapping(tableName, baseDN, OUName, filterAttributeName);
+
+ if(filterColumnName == null) throw new NullPointerException("JDBC Error: Could not find matching column name for attribute: '" + filterAttributeName + "'. Please check if mapping was succesful.");
+ columnDataType = jdbcm.getTableColumnDataType(tableName, filterColumnName);
+ }
+
+ //Handle the like operator.
+ if(columnDataType != Integer.class){
+ String filterAttributeValue = subStringFilterSplitter[1];
+ String filterColumnValue = "'" + filterAttributeValue + "'";
+ filterAttributeValue = filterAttributeValue.replace("*", "\\*");
+ filterAttributeValue = filterAttributeValue.replace("(", "\\(");
+ filterAttributeValue = filterAttributeValue.replace(")", "\\)");
+
+ if(filterColumnValue.length() > 3 && filterColumnValue.contains("*")){
+ filterColumnValue = filterColumnValue.replace("*", "%");
+
+ if(subStringFilter.contains("!=")) subStringFilter = subStringFilter.replace("!=", " not like ");
+ else subStringFilter = subStringFilter.replace("=", " like ");
+ }
+ subStringFilter = subStringFilter.replaceFirst(filterAttributeValue, filterColumnValue);
+ }
+ subStringFilter = subStringFilter.replaceFirst(filterAttributeName, filterColumnName);
+
+ if(j != 0 || i != 0) convertedFilterString = convertedFilterString.concat(operationString);
+ convertedFilterString = convertedFilterString.concat(subStringFilter);
+ }
+
+ if(multipleSubStrings && i < subStringCount -1) convertedFilterString = "(" + convertedFilterString + ")";
+ }
}
-
- if(multipleSubStrings && i < subStringCount -1) convertedFilterString = "(" + convertedFilterString + ")";
+ return convertedFilterString;
}
- return convertedFilterString;
+ catch(NullPointerException e){
+ return "Err:" + e.getMessage();
+ }
}
+ /**
+ * Returns the search entries of the last search request.
+ *
+ * @return A list of entries of the last search request.
+ */
public List<Entry> getSearchEntries()
{
return searchEntries;
}
+ /**
+ * Search the Database Server using the provided search request.
+ *
+ * @param request
+ * The search request.
+ * @param handler
+ * A search result handler which can be used to asynchronously process the
+ * search result entries and references as they are received, may be null.
+ * @return The result of the operation.
+ * @throws ErrorResultException
+ * If the result code indicates that the request failed for some
+ * reason.
+ * @throws SQLException
+ * If the SQL query has an invalid format.
+ * @throws NullPointerException
+ * If {@code request} was {@code null}, or if
+ * a corresponding mapping value could not be found in the mapping component.
+ */
@Override
public Result search(SearchRequest request, SearchResultHandler handler) throws ErrorResultException
{
Result r;
try{
+ //Split up the DN the of the request.
final DN DN = request.getName();
final int DNSize = DN.size();
final String baseDN = DN.parent(DNSize - 2).toString();
@@ -568,49 +870,98 @@
OU = DN.parent(0).rdn();
OUName = OU.getFirstAVA().getAttributeValue().toString();
}
+ List<String> returnAttributeNames = request.getAttributes();
+ final List<String> removeAttributesList = new ArrayList<String>();
+ //Get all column names to be returned to return full records.
+ if(returnAttributeNames == null){
+ if(OU != null){
+ returnAttributeNames = jdbcm.getOrganizationalUnitAttributes(baseDN, OUName);
- final List<String> returnAttributeNames = request.getAttributes();
- final List<String> returnColumnNames = new ArrayList<String>();
+ if(returnAttributeNames == null) throw new NullPointerException("JDBC Error: Could not find any matching attributes in OU: '" + OUName + "'.");
+ final String tableName = jdbcm.getTableNameFromMapping(baseDN, OUName);
- final Filter searchFilter = request.getFilter();
- final String convertedFilterString = convertSearchFilter(searchFilter, baseDN, OUName);
+ for(Iterator<String> iterAttributes = returnAttributeNames.iterator(); iterAttributes.hasNext();){
+ String returnAttributeName = iterAttributes.next();
+ final String returnColumnName = jdbcm.getColumnNameFromMapping(tableName, baseDN, OUName, returnAttributeName);
- if(returnAttributeNames != null){
+ if(returnColumnName == null) removeAttributesList.add(returnAttributeName);
+ }
+ returnAttributeNames.removeAll(removeAttributesList);
+ }
+ else{
+ final List<String> OUList = jdbcm.getOrganizationalUnits(baseDN);
- for(Iterator<String> iter = returnAttributeNames.iterator();iter.hasNext();){
+ if(OUList == null) throw new NullPointerException("JDBC Error: Could not find any matching organizational units in DN: '" + baseDN + "'.");
- if(OU == null){
- final String returnAttributeName = iter.next();
- final List<String> OUList = jdbcm.getOrganizationalUnits(baseDN);
+ for(Iterator<String> iterOU = OUList.iterator(); iterOU.hasNext();){
+ OUName = iterOU.next();
+ final String tableName = jdbcm.getTableNameFromMapping(baseDN, OUName);
+ returnAttributeNames = jdbcm.getOrganizationalUnitAttributes(baseDN, OUName);
- for(Iterator<String> iterOU = OUList.iterator(); iterOU.hasNext();){
- OUName = iterOU.next();
- final String tableName = jdbcm.getTableNameFromMapping(baseDN, OUName);
+ for(Iterator<String> iterAttributes = returnAttributeNames.iterator(); iterAttributes.hasNext();){
+ String returnAttributeName = iterAttributes.next();
final String returnColumnName = jdbcm.getColumnNameFromMapping(tableName, baseDN, OUName, returnAttributeName);
- if(returnColumnName == null) continue;
- else returnColumnNames.add(returnColumnName);
- break;
+ if(returnColumnName == null) removeAttributesList.add(returnAttributeName);
}
- }
- else {
- final String returnAttributeName = iter.next();
- final String tableName = jdbcm.getTableNameFromMapping(baseDN, OUName);
- final String returnColumnName = jdbcm.getColumnNameFromMapping(tableName, baseDN, OUName, returnAttributeName);
- returnColumnNames.add(returnColumnName);
+ returnAttributeNames.removeAll(removeAttributesList);
}
}
}
+ //Convert the search filter.
+ final Filter searchFilter = request.getFilter();
+ final String convertedFilterString = convertSearchFilter(searchFilter, baseDN, OUName);
+
+ if(convertedFilterString.startsWith("Err:")){
+ String[] errorStringSplitter = convertedFilterString.split("Err:");
+ throw new NullPointerException(errorStringSplitter[1]);
+ }
+ final List<String> returnColumnNames = new ArrayList<String>();
+
+ //Search mapping for the corresponding column name for each return attribute.
+ for(Iterator<String> iter = returnAttributeNames.iterator();iter.hasNext();){
+
+ if(OU == null){
+ final String returnAttributeName = iter.next();
+ final List<String> OUList = jdbcm.getOrganizationalUnits(baseDN);
+
+ if(OUList == null) throw new NullPointerException("JDBC Error: Could not find any matching organizational units in DN: '" + baseDN + "'.");
+
+ for(Iterator<String> iterOU = OUList.iterator(); iterOU.hasNext();){
+ OUName = iterOU.next();
+ final String tableName = jdbcm.getTableNameFromMapping(baseDN, OUName);
+ final String returnColumnName = jdbcm.getColumnNameFromMapping(tableName, baseDN, OUName, returnAttributeName);
+
+ if(returnColumnName == null) continue;
+ else returnColumnNames.add(returnColumnName);
+ break;
+ }
+ }
+ else {
+ final String returnAttributeName = iter.next();
+ final String tableName = jdbcm.getTableNameFromMapping(baseDN, OUName);
+
+ if(tableName == null) throw new NullPointerException("JDBC Error: Could not find matching table name for OU: '" + OUName + "' in DN: '" + baseDN + "'. Please check if mapping was succesful.");
+ final String returnColumnName = jdbcm.getColumnNameFromMapping(tableName, baseDN, OUName, returnAttributeName);
+
+ if(returnColumnName == null) throw new NullPointerException("JDBC Error: Could not find matching column name for attribute: '" + returnAttributeName + "'. Please check if mapping was succesful.");
+ returnColumnNames.add(returnColumnName);
+ }
+ }
+
String selectString = "";
String fromString = "";
String whereString = convertedFilterString;
- if(returnColumnNames.isEmpty()) selectString = "*";
+ if(returnAttributeNames.isEmpty()) selectString = "*";
+ //Build the SQL SELECT string.
if(OU == null){
final List<String> OUList = jdbcm.getOrganizationalUnits(baseDN);
+ if(OUList == null) throw new NullPointerException("JDBC Error: Could not find any matching organizational units in DN: '" + baseDN + "'.");
+
for(int i = 0; i < OUList.size(); i++){
final String currentOU = OUList.get(i);
final String currentTable = jdbcm.getTableNameFromMapping(baseDN, currentOU);
@@ -634,6 +985,8 @@
}
else{
final String selectTable = jdbcm.getTableNameFromMapping(baseDN, OUName);
+ if(selectTable == null) throw new NullPointerException("JDBC Error: Could not find matching table name for OU: '" + OUName + "' in DN: '" + baseDN + "'. Please check if mapping was succesful.");
+
fromString = fromString.concat(selectTable);
for(int j = 0; j < returnColumnNames.size(); j++){
@@ -646,20 +999,22 @@
}
if(rDN != null){
- final String tableName = jdbcm.getTableNameFromMapping(baseDN, OUName);
- final String columnName = jdbcm.getColumnNameFromMapping(tableName, baseDN, OUName, rDNAttributeName);
+ final String columnName = jdbcm.getColumnNameFromMapping(selectTable, baseDN, OUName, rDNAttributeName);
+
+ if(columnName == null) throw new NullPointerException("JDBC Error: Could not find matching column name for attribute: '" + rDNAttributeName + "'. Please check if mapping was succesful.");
whereString = columnName + "='" + rDNAttributeValue + "'";
}
}
+ //Build the SQL query.
+ final Statement st = connection.createStatement();
String sql = "SELECT " + selectString + " FROM " + fromString;
if(!whereString.isEmpty()) sql = sql.concat(" WHERE " + whereString);
-
- final Statement st = connection.createStatement();
ResultSet rs = st.executeQuery(sql);
ResultSetMetaData rsmd = rs.getMetaData();
+ //Fill the entries result for this query.
searchEntries.clear();
while (rs.next()) {
Entry e = new LinkedHashMapEntry();
@@ -670,13 +1025,21 @@
searchEntries.add(e);
}
r = Responses.newResult(ResultCode.SUCCESS);
- }catch (SQLException e){
+ }catch (SQLException e) {
System.out.println(e.toString());
r = Responses.newResult(ResultCode.OPERATIONS_ERROR);
+ r.setCause(e);
+ }catch (NullPointerException e){
+ System.out.println(e.toString());
+ r = Responses.newCompareResult(ResultCode.OPERATIONS_ERROR);
+ r.setCause(e);
}
return r;
}
+ /**
+ * {@inheritDoc}
+ */
@Override
public String toString()
{
--
Gitblit v1.10.0