mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Glenn Van Lint
23.59.2013 bca086082cad122659ddfe96456fd7b8913d4bd5
opendj3/opendj-virtual/src/main/java/org/forgerock/opendj/virtual/JDBCMapper.java
@@ -26,12 +26,12 @@
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.forgerock.opendj.ldap.Attribute;
import org.forgerock.opendj.ldap.Connection;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.ErrorResultException;
@@ -39,11 +39,17 @@
import org.forgerock.opendj.ldap.SearchResultReferenceIOException;
import org.forgerock.opendj.ldap.SearchScope;
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
import org.forgerock.opendj.ldap.schema.AttributeType;
import org.forgerock.opendj.ldap.schema.Schema;
import org.forgerock.opendj.ldif.ConnectionEntryReader;
import org.forgerock.opendj.ldif.EntryReader;
public final class JDBCMapper {
/**
 * The mapping for the JDBCConnection which holds information about the database
 * and directory structures.
 */
public final class JDBCMapper
{
  final private java.sql.Connection jdbcConnection;
  final private Connection ldapConnection;
  private String dbName;
@@ -56,35 +62,89 @@
  final private Map<String, ArrayList<String>> organizationalUnitAttributesMap = new HashMap<String, ArrayList<String>>();
  private Map<String, String> SQLToLDAPMap = new HashMap<String, String>();
  JDBCMapper(final Connection jdbcconnection, final Connection ldapconnection) {
  /**
   * Creates a new JDBC mapping.
   *
   * @param jdbcconnection
   *            The JDBCConnection for the Database Server.
   * @param ldapconnection
   *            The LDAPConnection for the Directory Server.
   */
  JDBCMapper(final Connection jdbcconnection, final Connection ldapconnection)
  {
    this.jdbcConnection = ((JDBCConnection) jdbcconnection).getSqlConnection();
    this.ldapConnection = ldapconnection;
  }
  public void setDbName(String DBName){
  /**
   * Sets the SQL database name for this mapping.
   *
   * @param DBName
   *            The database name.
   */
  public void setDatabaseName(String DBName)
  {
    this.dbName = DBName;
  }
  public void closeConnections() throws SQLException{
  /**
   * Releases this Connection object's database/directory and JDBC/LDAP resources immediately instead of
   * waiting for them to be automatically released.
   *
   * Calling the method close on a Connection object that is already closed is a no-op.
   *
   * @throws SQLException
   *            If a database access error occurs.
   */
  public void closeConnections() throws SQLException
  {
    this.jdbcConnection.close();
    this.ldapConnection.close();
  }
  public void fillMaps() throws ErrorResultException, SQLException, IOException{
  /**
   * Fills this mapping with the structure of the currently connected database.
   *
   * @throws ErrorResultException
   *            If the result code indicates that the request failed for some
   *            reason.
   * @throws SQLException
   *            If a database access error occurs.
   * @throws IOException
   *            If an I/O exception error occurs.
   */
  public void fillMaps() throws ErrorResultException, SQLException, IOException
  {
    fillBaseDNList();
    fillTablesList();
    fillTableColumnsMap();
    fillOrganizationalUnitsAndAttributesMap();
  }
  private void fillBaseDNList() throws IOException{
  /**
   * Fills this mapping with the base distinguished names of the currently connected directory.
   *
   * @throws IOException
   *            If an I/O exception error occurs.
   */
  private void fillBaseDNList() throws IOException
  {
    final EntryReader reader = this.ldapConnection.search(" ", SearchScope.SINGLE_LEVEL, "objectClass=*");
    while(reader.hasNext()){
      baseDNList.add(reader.readEntry().getName().toString());
    }
  }
  private void fillTablesList() throws SQLException{
  /**
   * Fills this mapping with the tables of the currently connected database.
   *
   * @throws SQLException
   *            If a database access error occurs.
   */
  private void fillTablesList() throws SQLException
  {
    /*For connection to h2 database, use "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE " +
    "TABLE_TYPE = 'TABLE' AND TABLE_SCHEMA = 'PUBLIC'";*/
    final String sql = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE " +
        "TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA = '" + this.dbName + "'";
    final Statement st = this.jdbcConnection.createStatement();
@@ -95,7 +155,21 @@
    }
  }
  private void fillTableColumnsMap() throws SQLException, ErrorResultIOException, SearchResultReferenceIOException{
  /**
   * Fills this mapping with the columns for each table of the currently connected database. Also checks
   * the column's data type and not null definition.
   *
   * @throws SQLException
   *            If the result code indicates that the request failed for some
   *            reason.
   * @throws ErrorResultIOException
   *            If an I/O exception error occurs in the result code.
   * @throws SearchResultReferenceIOException
   *            If an iteration over a set of search results using a ConnectionEntryReader encounters
   *            a SearchResultReference.
   */
  private void fillTableColumnsMap() throws SQLException, ErrorResultIOException, SearchResultReferenceIOException
  {
    for(int i =0; i < tablesList.size(); i++){
      final String tableName = tablesList.get(i);
      final String sql = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '" + tableName + "'";
@@ -115,45 +189,21 @@
      tableColumnsMap.put(tableName, columnsList);
    }
  }
  public ArrayList<String> getTables() throws SQLException{
    return tablesList;
  }
  public ArrayList<String> getBaseDNs(){
    return baseDNList;
  }
  public ArrayList<String> getTableColumns(final String tableName) throws SQLException{
    final ArrayList<String> tableColumnsList = tableColumnsMap.get(tableName);
    return tableColumnsList;
  }
  public boolean getTableColumnNullable(final String tableName, final String columnName){
    final String mappingKey = tableName + ":" + columnName;
    final String nullable = tableColumnNullableMap.get(mappingKey);
    final String nullableString = "NO";
    if(nullable.equals(nullableString)) return false;
    else return true;
  }
  public Object getTableColumnDataType(final String tableName, final String columnName){
    final String mappingKey = tableName + ":" + columnName;
    final String mappingValue = tableColumnDataTypeMap.get(mappingKey);
    final String objectTypeString = "int";
    if(mappingValue.equals(objectTypeString)) return Integer.class;
    return String.class;
  }
  public ArrayList<String> getOrganizationalUnits(final String baseDN){
    return organizationalUnitsMap.get(baseDN);
  }
  public ArrayList<String> getOrganizationalUnitAttributes(final String baseDN, final String organizationalUnitName){
    return organizationalUnitAttributesMap.get(baseDN + ":" + organizationalUnitName);
  }
  private void fillOrganizationalUnitsAndAttributesMap() throws ErrorResultException, ErrorResultIOException, SearchResultReferenceIOException{
  /**
   * Fills this mapping with the organizational units and attributes for for each organizational unit
   * of the currently connected directory.
   *
   * @throws ErrorResultException
   *            If a database access error occurs.
   * @throws ErrorResultIOException
   *            If an I/O exception error occurs in the result code.
   * @throws SearchResultReferenceIOException
   *            If an iteration over a set of search results using a ConnectionEntryReader encounters
   *            a SearchResultReference.
   */
  private void fillOrganizationalUnitsAndAttributesMap() throws ErrorResultException, ErrorResultIOException, SearchResultReferenceIOException
  {
    for(int i = 0; i < baseDNList.size(); i++){
      final String baseDN = baseDNList.get(i);
      final ConnectionEntryReader baseDNReader = ldapConnection.search(baseDN, SearchScope.SINGLE_LEVEL, "objectClass=*");
@@ -165,16 +215,17 @@
        final String organizationalUnitName = DN.valueOf(organizationalUnitDNName).rdn().getFirstAVA().getAttributeValue().toString();
        organizationalUnitsList.add(organizationalUnitName);
        final ConnectionEntryReader DNReader = ldapConnection.search(organizationalUnitDNName, SearchScope.SINGLE_LEVEL, "objectClass=*");
        Schema.readSchemaForEntry(ldapConnection, DN.valueOf(organizationalUnitDNName));
        final Collection<AttributeType> attributeTypes = Schema.getCoreSchema().getAttributeTypes();
        final ArrayList<String> attributesList;
        if(DNReader.hasNext()){
          final Iterator<Attribute> it = DNReader.readEntry().getAllAttributes().iterator();
        if(attributeTypes.iterator().hasNext()){
          final Iterator<AttributeType> it = attributeTypes.iterator();
          attributesList = new ArrayList<String>();
          while(it.hasNext()){
            final Attribute att = it.next();
            attributesList.add(att.getAttributeDescriptionAsString());
            final AttributeType at = it.next();
            attributesList.add(at.getNameOrOID());
          }
        }
        else{
@@ -187,7 +238,127 @@
    }
  }
  public void addCurrentMapToMapping(final String tableName, final String[] columnNames, final String baseDN, final String OUName, final String[] attributeNames){
  /**
   * Returns a list of table names of the currently connected database.
   *
   * @return A list of table names.
   * @throws SQLException
   *            If a database access error occurs.
   */
  public ArrayList<String> getTables() throws SQLException
  {
    return tablesList;
  }
  /**
   * Returns a list of base distinguished names of the currently connected directory.
   *
   * @return A list of base distinguished names.
   * @throws SQLException
   *            If a database access error occurs.
   */
  public ArrayList<String> getBaseDNs()
  {
    return baseDNList;
  }
  /**
   * Returns a list of column names in the provided table name of the currently connected database.
   *
   * @param tableName
   *            The table name of the columns to retrieve.
   * @return A list of column names.
   * @throws SQLException
   *            If a database access error occurs.
   */
  public ArrayList<String> getTableColumns(final String tableName) throws SQLException
  {
    final ArrayList<String> tableColumnsList = tableColumnsMap.get(tableName);
    return tableColumnsList;
  }
  /**
   * Returns a boolean value which indicates whether the specified column name has NOT NULL defined
   * in the provided table name of the currently connected database.
   *
   * @param tableName
   *            The table name in which to search.
   * @param columnName
   *            The column name in which to search.
   * @return A boolean value to indicate the value of NOT NULL in the column.
   */
  public boolean getTableColumnNullable(final String tableName, final String columnName)
  {
    final String mappingKey = tableName + ":" + columnName;
    final String nullable = tableColumnNullableMap.get(mappingKey);
    final String nullableString = "NO";
    if(nullable.equals(nullableString)) return false;
    else return true;
  }
  /**
   * Returns an object which indicates the data type of the specified column name in
   * the provided table name of the currently connected database.
   *
   * @param tableName
   *            The table name in which to search.
   * @param columnName
   *            The column name in which to search.
   * @return A boolean value to indicate the value of NOT NULL in the column.
   */
  public Object getTableColumnDataType(final String tableName, final String columnName)
  {
    final String mappingKey = tableName + ":" + columnName;
    final String mappingValue = tableColumnDataTypeMap.get(mappingKey);
    final String objectTypeString = "int";
    if(mappingValue.equals(objectTypeString)) return Integer.class;
    return String.class;
  }
  /**
   * Returns a list of organizational unit names in the provided base distinguished name
   * of the currently connected directory.
   *
   * @param baseDN
   *            The base distinguished name of the organizational units to retrieve.
   * @return A list of organizational unit names.
   */
  public ArrayList<String> getOrganizationalUnits(final String baseDN)
  {
    return organizationalUnitsMap.get(baseDN);
  }
  /**
   * Returns a list of attributes within the specified organizational unit name in
   * the provided base distinguished name of the currently connected directory.
   *
   * @param baseDN
   *            The base distinguished name in which to search.
   * @param organizationalUnitName
   *            The organizational unit name in which to search.
   * @return A a list of attributes.
   */
  public ArrayList<String> getOrganizationalUnitAttributes(final String baseDN, final String organizationalUnitName)
  {
    return organizationalUnitAttributesMap.get(baseDN + ":" + organizationalUnitName);
  }
  /**
   * Create a map with the provided parameters and save it to the mapping.
   *
   * @param tableName
   *            The database table name to save.
   * @param columnNames
   *            The database column names to save.
   * @param baseDN
   *            The directory base distinguished name to save.
   * @param OUName
   *            The directory organizational unit name to save.
   * @param attributeNames
   *            The directory attribute name to save.
   */
  public void addCurrentMapToMapping(final String tableName, final String[] columnNames, final String baseDN, final String OUName, final String[] attributeNames)
  {
    String mappingKey, mappingValue;
    for(int i = 0; i < columnNames.length; i++){
@@ -197,11 +368,29 @@
    }
  }
  public Map<String, String> getMapping(){
  /**
   * Returns a the full mapping of the directory structure to the database structure.
   *
   * @return A full mapping of directory to database structure.
   */
  public Map<String, String> getMapping()
  {
    return SQLToLDAPMap;
  }
  public Map<String, String> loadCurrentMapFromMapping(final String tableName, String baseDN, String DN) {
  /**
   * Returns a map which holds the provided parameters.
   *
   * @param tableName
   *            The database table name in which to search.
   * @param baseDN
   *            The directory base distinguished name in which to search.
   * @param DN
   *            The relative distinguished name.
   * @return A a list of attributes.
   */
  public Map<String, String> loadCurrentMapFromMapping(final String tableName, String baseDN, String DN)
  {
    baseDN = baseDN.replace(" ", "");
    String mappingKey, mappingValue;
    final ArrayList<String> tableColumnsList = tableColumnsMap.get(tableName);
@@ -216,15 +405,32 @@
    return currentMap;
  }
  public void loadMappingConfig(Map<String, String> m){
    this.SQLToLDAPMap = m;
  /**
   * Sets the full mapping to the mapping provided.
   *
   * @param mapping
   *            The mapping to which to set the full mapping to.
   */
  public void loadMappingConfig(Map<String, String> mapping)
  {
    this.SQLToLDAPMap = mapping;
  }
  public String getTableNameFromMapping(String DN, final String organizationalUnit) {
    DN = DN.replace(" ", "");
  /**
   * Returns the table name from the mapping that corresponds to the parameters provided.
   *
   * @param baseDN
   *            The directory base distinguished name in which to search.
   * @param organizationalUnit
   *            The directory organizational unit to search for.
   * @return The table name that is mapped to the provided distinguished name.
   */
  public String getTableNameFromMapping(String baseDN, final String organizationalUnit)
  {
    baseDN = baseDN.replace(" ", "");
    for (Entry<String, String> entry : SQLToLDAPMap.entrySet()) {
      final String mappingValue = entry.getValue();
      if (mappingValue.contains(DN + ":" + organizationalUnit)) {
      if (mappingValue.contains(baseDN + ":" + organizationalUnit)) {
        final String mappingKey = entry.getKey();
        final String stringSplitter[] = mappingKey.split(":");
        final String tableName = stringSplitter[0];
@@ -234,7 +440,21 @@
    return null;
  }
  public String getColumnNameFromMapping(final String tableName, String baseDN, final String organizationalUnitName, final String attributeName) {
  /**
   * Returns the column name from the mapping that corresponds to the parameters provided.
   *
   * @param tableName
   *            The database table name in which to search.
   * @param baseDN
   *            The directory base distinguished name in which to search.
   * @param organizationalUnitName
   *            The directory organizational unit name in which to search.
   * @param attributeName
   *            The directory attribute name to search for.
   * @return The column name that is mapped to the provided attribute name.
   */
  public String getColumnNameFromMapping(final String tableName, String baseDN, final String organizationalUnitName, final String attributeName)
  {
    baseDN = baseDN.replace(" ", "");
    for (Entry<String, String> entry : SQLToLDAPMap.entrySet()) {
      final String mappingValue = entry.getValue();
@@ -250,5 +470,3 @@
    return null;
  }
}