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

Jean-Noël Rouvignac
19.03.2016 17ec2cfa9d04e6942a694ab5c3778ac26f17bb35
opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java
@@ -52,6 +52,7 @@
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.config.server.ConfigChangeResult;
import org.forgerock.opendj.config.server.ConfigException;
import org.forgerock.opendj.config.server.ConfigurationChangeListener;
import org.forgerock.opendj.ldap.AVA;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ConditionResult;
@@ -64,13 +65,11 @@
import org.forgerock.opendj.ldap.schema.CoreSchema;
import org.forgerock.opendj.ldap.schema.MatchingRule;
import org.forgerock.opendj.ldap.schema.ObjectClassType;
import org.forgerock.opendj.config.server.ConfigurationChangeListener;
import org.forgerock.opendj.server.config.server.SchemaBackendCfg;
import org.opends.server.api.AlertGenerator;
import org.opends.server.api.Backend;
import org.opends.server.api.Backupable;
import org.opends.server.api.ClientConnection;
import org.opends.server.types.Entry;
import org.opends.server.core.AddOperation;
import org.opends.server.core.DeleteOperation;
import org.opends.server.core.DirectoryServer;
@@ -96,6 +95,7 @@
import org.opends.server.types.DITContentRule;
import org.opends.server.types.DITStructureRule;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.Entry;
import org.opends.server.types.ExistingFileBehavior;
import org.opends.server.types.IndexType;
import org.opends.server.types.InitializationException;
@@ -256,7 +256,6 @@
    ObjectClass subschemaOC = DirectoryServer.getObjectClass(OC_SUBSCHEMA, true);
    schemaObjectClasses.put(subschemaOC, OC_SUBSCHEMA);
    configEntryDN = configEntry.getName();
    baseDNs = cfg.getBaseDN();
@@ -273,7 +272,6 @@
    modifyTimestamp =
         GeneralizedTimeSyntax.createGeneralizedTimeValue(newModifyTime);
    // Get the set of user-defined attributes for the configuration entry.  Any
    // attributes that we don't recognize will be included directly in the
    // schema entry.
@@ -318,7 +316,6 @@
      }
    }
    // Identify any differences that may exist between the concatenated schema
    // file from the last online modification and the current schema files.  If
    // there are any differences, then they should be from making changes to the
@@ -417,7 +414,6 @@
      logger.error(ERR_SCHEMA_ERROR_DETERMINING_SCHEMA_CHANGES, getExceptionMessage(e));
    }
    // Register with the Directory Server as a configurable component.
    currentConfig.addSchemaChangeListener(this);
  }
@@ -440,8 +436,6 @@
    }
  }
  /**
   * Indicates whether the provided attribute is one that is used in the
   * configuration of this backend.
@@ -522,7 +516,6 @@
    return null;
  }
  /**
   * Generates and returns a schema entry for the Directory Server.
   *
@@ -571,9 +564,7 @@
      }
    }
    /*
     * Add the schema definition attributes.
     */
    /* Add the schema definition attributes. */
    Schema schema = DirectoryServer.getSchema();
    buildSchemaAttribute(schema.getAttributeTypes(), userAttrs,
        operationalAttrs, attributeTypesType, includeSchemaFile,
@@ -642,8 +633,6 @@
    return e;
  }
  private void addAttributeToSchemaEntry(Attribute attribute,
      Map<AttributeType, List<Attribute>> userAttrs,
      Map<AttributeType, List<Attribute>> operationalAttrs)
@@ -659,8 +648,6 @@
    attrs.add(attribute);
  }
  private void buildSchemaAttribute(Collection<?> elements,
      Map<AttributeType, List<Attribute>> userAttrs,
      Map<AttributeType, List<Attribute>> operationalAttrs,
@@ -676,10 +663,7 @@
    AttributeBuilder builder = new AttributeBuilder(schemaAttributeType);
    for (Object element : elements)
    {
      /*
       * Add the file name to the description of the element if this was
       * requested by the caller.
       */
      /* Add the file name to the description of the element if this was requested by the caller. */
      String value;
      if (includeSchemaFile && element instanceof CommonSchemaElements)
      {
@@ -748,7 +732,6 @@
                                   message);
    }
    ArrayList<Modification> mods = new ArrayList<>(modifyOperation.getModifications());
    if (mods.isEmpty())
    {
@@ -918,7 +901,6 @@
          break;
        case DELETE:
          if (a.isEmpty())
          {
@@ -1073,7 +1055,6 @@
          break;
        case REPLACE:
          if (!m.isInternal()
              && !modifyOperation.isSynchronizationOperation())
@@ -1100,7 +1081,6 @@
      }
    }
    // If we've gotten here, then everything looks OK, re-write all the
    // modified Schema Files.
    updateSchemaFiles(newSchema, modifiedSchemaFiles);
@@ -1108,7 +1088,6 @@
    // Finally set DirectoryServer to use the new Schema.
    DirectoryServer.setSchema(newSchema);
    DN authzDN = modifyOperation.getAuthorizationDN();
    if (authzDN == null)
    {
@@ -1120,8 +1099,6 @@
                           System.currentTimeMillis());
  }
  /**
   * Re-write all schema files using the provided new Schema and list of
   * modified files.
@@ -1170,15 +1147,12 @@
      cleanUpTempSchemaFiles(tempSchemaFiles);
    }
    // Create a single file with all of the concatenated schema information
    // that we can use on startup to detect whether the schema files have been
    // edited with the server offline.
    Schema.writeConcatenatedSchema();
  }
  /**
   * Handles all processing required for adding the provided attribute type to
   * the given schema, replacing an existing type if necessary, and ensuring all
@@ -1460,8 +1434,6 @@
    }
  }
  /**
   * Handles all processing required for adding the provided objectclass to the
   * given schema, replacing an existing class if necessary, and ensuring
@@ -1513,7 +1485,6 @@
      }
    }
    // Make sure that the new objectclass doesn't reference an undefined
    // superior class, or an undefined required or optional attribute type,
    // and that none of them are OBSOLETE.
@@ -1565,7 +1536,6 @@
      }
    }
    // If there is no existing class, then we're adding a new objectclass.
    // Otherwise, we're replacing an existing one.
    if (existingClass == null)
@@ -1582,8 +1552,6 @@
    }
  }
  /**
   * Handles all processing required to remove the provided objectclass from the
   * server schema, ensuring all other metadata is properly updated.  Note that
@@ -1626,7 +1594,6 @@
      throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
    }
    // See if there is another modification later to add the objectclass back
    // into the schema.  If so, then it's a replace and we should ignore the
    // remove because adding it back will handle the replace.
@@ -1667,7 +1634,6 @@
      }
    }
    // Make sure that the objectclass isn't used as the superior class for any
    // other objectclass.
    for (ObjectClass oc : schema.getObjectClasses().values())
@@ -1684,7 +1650,6 @@
      }
    }
    // Make sure that the objectclass isn't used as the structural class for
    // any name form.
    List<NameForm> mappedForms = schema.getNameForm(removeClass);
@@ -1701,7 +1666,6 @@
      throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
    }
    // Make sure that the objectclass isn't used as a structural or auxiliary
    // class for any DIT content rule.
    for (DITContentRule dcr : schema.getDITContentRules().values())
@@ -1715,7 +1679,6 @@
      }
    }
    // If we've gotten here, then it's OK to remove the objectclass from the
    // schema.
    schema.deregisterObjectClass(removeClass);
@@ -1726,8 +1689,6 @@
    }
  }
  /**
   * Handles all processing required for adding the provided name form to the
   * the given schema, replacing an existing name form if necessary, and
@@ -1778,7 +1739,6 @@
      }
    }
    // Make sure that the new name form doesn't reference an undefined
    // structural class, or an undefined required or optional attribute type, or
    // that any of them are marked OBSOLETE.
@@ -1834,7 +1794,6 @@
      }
    }
    // If there is no existing class, then we're adding a new name form.
    // Otherwise, we're replacing an existing one.
    if (existingNF == null)
@@ -1851,8 +1810,6 @@
    }
  }
  /**
   * Handles all processing required to remove the provided name form from the
   * server schema, ensuring all other metadata is properly updated.  Note that
@@ -1894,7 +1851,6 @@
      throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
    }
    // See if there is another modification later to add the name form back
    // into the schema.  If so, then it's a replace and we should ignore the
    // remove because adding it back will handle the replace.
@@ -1935,7 +1891,6 @@
      }
    }
    // Make sure that the name form isn't referenced by any DIT structure
    // rule.
    DITStructureRule dsr = schema.getDITStructureRule(removeNF);
@@ -1946,7 +1901,6 @@
      throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
    }
    // If we've gotten here, then it's OK to remove the name form from the
    // schema.
    schema.deregisterNameForm(removeNF);
@@ -1957,8 +1911,6 @@
    }
  }
  /**
   * Handles all processing required for adding the provided DIT content rule to
   * the given schema, replacing an existing rule if necessary, and ensuring
@@ -2007,7 +1959,6 @@
      }
    }
    // Get the structural class for the new DIT content rule and see if there's
    // already an existing rule that is associated with that class.  If there
    // is, then it will only be acceptable if it's the DIT content rule that we
@@ -2023,7 +1974,6 @@
      throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
    }
    // Make sure that the new DIT content rule doesn't reference an undefined
    // structural or auxiliary class, or an undefined required, optional, or
    // prohibited attribute type.
@@ -2118,7 +2068,6 @@
      }
    }
    // If there is no existing rule, then we're adding a new DIT content rule.
    // Otherwise, we're replacing an existing one.
    if (existingDCR == null)
@@ -2136,8 +2085,6 @@
    }
  }
  /**
   * Handles all processing required to remove the provided DIT content rule
   * from the server schema, ensuring all other metadata is properly updated.
@@ -2174,7 +2121,6 @@
      throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
    }
    // Since DIT content rules don't have any dependencies, then we don't need
    // to worry about the difference between a remove or a replace.  We can
    // just remove the DIT content rule now, and if it is added back later then
@@ -2187,8 +2133,6 @@
    }
  }
  /**
   * Handles all processing required for adding the provided DIT structure rule
   * to the given schema, replacing an existing rule if necessary, and ensuring
@@ -2270,7 +2214,6 @@
      throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
    }
    // Make sure that the new DIT structure rule doesn't reference an undefined
    // name form or superior DIT structure rule.
    if (! schema.hasNameForm(nameForm.getOID()))
@@ -2286,7 +2229,6 @@
      throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message);
    }
    // If there are any superior rules, then make sure none of them are marked
    // OBSOLETE.
    for (DITStructureRule dsr : ditStructureRule.getSuperiorRules())
@@ -2299,7 +2241,6 @@
      }
    }
    // If there is no existing rule, then we're adding a new DIT structure rule.
    // Otherwise, we're replacing an existing one.
    if (existingDSR == null)
@@ -2317,8 +2258,6 @@
    }
  }
  /**
   * Handles all processing required to remove the provided DIT structure rule
   * from the server schema, ensuring all other metadata is properly updated.
@@ -2363,7 +2302,6 @@
      throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
    }
    // See if there is another modification later to add the DIT structure rule
    // back into the schema.  If so, then it's a replace and we should ignore
    // the remove because adding it back will handle the replace.
@@ -2404,7 +2342,6 @@
      }
    }
    // Make sure that the DIT structure rule isn't the superior for any other
    // DIT structure rule.
    for (DITStructureRule dsr : schema.getDITStructureRulesByID().values())
@@ -2417,7 +2354,6 @@
      }
    }
    // If we've gotten here, then it's OK to remove the DIT structure rule from
    // the schema.
    schema.deregisterDITStructureRule(removeDSR);
@@ -2428,8 +2364,6 @@
    }
  }
  /**
   * Handles all processing required for adding the provided matching rule use
   * to the given schema, replacing an existing use if necessary, and ensuring
@@ -2482,7 +2416,6 @@
      }
    }
    // Get the matching rule for the new matching rule use and see if there's
    // already an existing matching rule use that is associated with that
    // matching rule.  If there is, then it will only be acceptable if it's the
@@ -2506,7 +2439,6 @@
      throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message);
    }
    // Make sure that the new matching rule use doesn't reference an undefined
    // attribute type.
    for (AttributeType at : matchingRuleUse.getAttributes())
@@ -2525,7 +2457,6 @@
      }
    }
    // If there is no existing matching rule use, then we're adding a new one.
    // Otherwise, we're replacing an existing matching rule use.
    if (existingMRU == null)
@@ -2543,8 +2474,6 @@
    }
  }
  /**
   * Handles all processing required to remove the provided matching rule use
   * from the server schema, ensuring all other metadata is properly updated.
@@ -2583,7 +2512,6 @@
      throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
    }
    // Since matching rule uses don't have any dependencies, then we don't need
    // to worry about the difference between a remove or a replace.  We can
    // just remove the DIT content rule now, and if it is added back later then
@@ -2661,8 +2589,6 @@
    }
  }
  /** Gets rid of the ldap syntax description. */
  private void removeLdapSyntaxDescription(String definition, Schema schema, Set<String> modifiedSchemaFiles)
      throws DirectoryException
@@ -2692,8 +2618,6 @@
    }
  }
  /**
   * Creates an empty entry that may be used as the basis for a new schema file.
   *
@@ -2721,9 +2645,6 @@
    return new Entry(dn, objectClasses,  userAttributes, operationalAttributes);
  }
  /**
   * Writes a temporary version of the specified schema file.
   *
@@ -2790,7 +2711,6 @@
      schemaEntry.putAttribute(attributeTypesType, newArrayList(builder.toAttribute()));
    }
    // Add all of the appropriate objectclasses to the schema entry.  We need
    // to be careful of the ordering to ensure that any superior classes in the
    // same file are written before the subordinate classes.
@@ -2812,7 +2732,6 @@
      schemaEntry.putAttribute(objectClassesType, newArrayList(builder.toAttribute()));
    }
    // Add all of the appropriate name forms to the schema entry.  Since there
    // is no hierarchical relationship between name forms, we don't need to
    // worry about ordering.
@@ -2835,7 +2754,6 @@
      schemaEntry.putAttribute(nameFormsType, newArrayList(builder.toAttribute()));
    }
    // Add all of the appropriate DIT content rules to the schema entry.  Since
    // there is no hierarchical relationship between DIT content rules, we don't
    // need to worry about ordering.
@@ -2855,7 +2773,6 @@
      schemaEntry.putAttribute(ditContentRulesType, newArrayList(builder.toAttribute()));
    }
    // Add all of the appropriate DIT structure rules to the schema entry.  We
    // need to be careful of the ordering to ensure that any superior rules in
    // the same file are written before the subordinate rules.
@@ -2877,7 +2794,6 @@
      schemaEntry.putAttribute(ditStructureRulesType, newArrayList(builder.toAttribute()));
    }
    // Add all of the appropriate matching rule uses to the schema entry.  Since
    // there is no hierarchical relationship between matching rule uses, we
    // don't need to worry about ordering.
@@ -2897,7 +2813,6 @@
      schemaEntry.putAttribute(matchingRuleUsesType, newArrayList(builder.toAttribute()));
    }
    if (FILE_USER_SCHEMA_ELEMENTS.equals(schemaFile))
    {
      Map<String, Attribute> attributes = schema.getExtraAttributes();
@@ -2913,15 +2828,14 @@
    LDIFExportConfig exportConfig =
         new LDIFExportConfig(tempFile.getAbsolutePath(),
                              ExistingFileBehavior.OVERWRITE);
    LDIFWriter ldifWriter = new LDIFWriter(exportConfig);
    ldifWriter.writeEntry(schemaEntry);
    ldifWriter.close();
    try (LDIFWriter ldifWriter = new LDIFWriter(exportConfig))
    {
      ldifWriter.writeEntry(schemaEntry);
    }
    return tempFile;
  }
  /**
   * Adds the definition for the specified attribute type to the provided set of
   * attribute values, recursively adding superior types as appropriate.
@@ -2970,8 +2884,6 @@
    addedTypes.add(attributeType);
  }
  /**
   * Adds the definition for the specified objectclass to the provided set of
   * attribute values, recursively adding superior classes as appropriate.
@@ -3020,8 +2932,6 @@
    addedClasses.add(objectClass);
  }
  /**
   * Adds the definition for the specified DIT structure rule to the provided
   * set of attribute values, recursively adding superior rules as appropriate.
@@ -3070,8 +2980,6 @@
    addedDSRs.add(ditStructureRule);
  }
  /**
   * Moves the specified temporary schema files in place of the active versions.
   * If an error occurs in the process, then this method will attempt to restore
@@ -3102,7 +3010,6 @@
      origFileList.add(new File(schemaInstanceDir, name + ".orig"));
    }
    // If there are any old ".orig" files laying around from a previous
    // attempt, then try to clean them up.
    for (File f : origFileList)
@@ -3113,7 +3020,6 @@
      }
    }
    // Copy all of the currently-installed files with a ".orig" extension.  If
    // this fails, then try to clean up the copies.
    try
@@ -3167,7 +3073,6 @@
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message, e);
    }
    // Try to copy all of the temporary files into place over the installed
    // files.  If this fails, then try to restore the originals.
    try
@@ -3247,8 +3152,6 @@
    }
  }
  /**
   * Creates a copy of the specified file.
   *
@@ -3259,14 +3162,10 @@
   */
  private void copyFile(File from, File to) throws IOException
  {
    byte[]           buffer        = new byte[4096];
    FileInputStream  inputStream   = null;
    FileOutputStream outputStream  = null;
    try
    try (FileInputStream inputStream = new FileInputStream(from);
        FileOutputStream outputStream = new FileOutputStream(to, false))
    {
      inputStream  = new FileInputStream(from);
      outputStream = new FileOutputStream(to, false);
      byte[] buffer = new byte[4096];
      int bytesRead = inputStream.read(buffer);
      while (bytesRead > 0)
      {
@@ -3274,14 +3173,8 @@
        bytesRead = inputStream.read(buffer);
      }
    }
    finally
    {
      close(inputStream, outputStream);
    }
  }
  /**
   * Performs any necessary cleanup in an attempt to delete any temporary schema
   * files that may have been left over after trying to install the new schema.
@@ -3332,7 +3225,6 @@
              matchedDN, null);
    }
    // If it's a onelevel or subordinate subtree search, then we will never
    // match anything since there isn't anything below the schema.
    SearchScope scope = searchOperation.getScope();
@@ -3342,7 +3234,6 @@
      return;
    }
    // Get the schema entry and see if it matches the filter.  If so, then send
    // it to the client.
    Entry schemaEntry = getSchemaEntry(baseDN, false);
@@ -3385,7 +3276,6 @@
                                   message);
    }
    // Write the root schema entry to it.  Make sure to close the LDIF
    // writer when we're done.
    try
@@ -3429,19 +3319,7 @@
  public LDIFImportResult importLDIF(LDIFImportConfig importConfig, ServerContext serverContext)
      throws DirectoryException
  {
    LDIFReader reader;
    try
    {
      reader = new LDIFReader(importConfig);
    }
    catch (Exception e)
    {
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
          ERR_MEMORYBACKEND_CANNOT_CREATE_LDIF_READER.get(e), e);
    }
    try
    try (LDIFReader reader = newLDIFReader(importConfig))
    {
      while (true)
      {
@@ -3481,12 +3359,20 @@
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
          ERR_MEMORYBACKEND_ERROR_DURING_IMPORT.get(e), e);
    }
    finally
    {
      close(reader);
    }
  }
  private LDIFReader newLDIFReader(LDIFImportConfig importConfig) throws DirectoryException
  {
    try
    {
      return new LDIFReader(importConfig);
    }
    catch (Exception e)
    {
      throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
          ERR_MEMORYBACKEND_CANNOT_CREATE_LDIF_READER.get(e), e);
    }
  }
  /**
   * Import an entry in a new schema by :
@@ -3689,7 +3575,6 @@
  {
    final ConfigChangeResult ccr = new ConfigChangeResult();
    // Check to see if we should apply a new set of base DNs.
    Set<DN> newBaseDNs;
    try
@@ -3710,12 +3595,10 @@
      newBaseDNs = null;
    }
    // Check to see if we should change the behavior regarding whether to show
    // all schema attributes.
    boolean newShowAllAttributes = backendCfg.isShowAllAttributes();
    // Check to see if there is a new set of user-defined attributes.
    ArrayList<Attribute> newUserAttrs = new ArrayList<>();
    try
@@ -3753,7 +3636,6 @@
      ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
    }
    if (ccr.getResultCode() == ResultCode.SUCCESS)
    {
      // Determine the set of DNs to add and delete.  When this is done, the
@@ -3802,22 +3684,17 @@
        }
      }
      showAllAttributes = newShowAllAttributes;
      userDefinedAttributes = newUserAttrs;
      LocalizableMessage message = INFO_SCHEMA_USING_NEW_USER_ATTRS.get();
      ccr.addMessage(message);
    }
    currentConfig = backendCfg;
    return ccr;
  }
  /**
   * Indicates whether to treat common schema attributes like user attributes
   * rather than operational attributes.
@@ -3830,8 +3707,6 @@
    return showAllAttributes;
  }
  /**
   * Specifies whether to treat common schema attributes like user attributes
   * rather than operational attributes.