opendj-sdk/opends/src/server/org/opends/server/backends/SchemaBackend.java
@@ -1846,14 +1846,19 @@ // Make sure that the attribute type isn't used as a required or optional // attribute type in any name form. for (NameForm nf : schema.getNameFormsByObjectClass().values()) for (List<NameForm> mappedForms : schema.getNameFormsByObjectClass().values()) { if (nf.getRequiredAttributes().contains(removeType) || nf.getOptionalAttributes().contains(removeType)) for(NameForm nf : mappedForms) { Message message = ERR_SCHEMA_MODIFY_REMOVE_AT_IN_NF.get( removeType.getNameOrOID(), nf.getNameOrOID()); throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); if (nf.getRequiredAttributes().contains(removeType) || nf.getOptionalAttributes().contains(removeType)) { Message message = ERR_SCHEMA_MODIFY_REMOVE_AT_IN_NF.get( removeType.getNameOrOID(), nf.getNameOrOID()); throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); } } } @@ -2158,11 +2163,17 @@ // Make sure that the objectclass isn't used as the structural class for // any name form. NameForm nf = schema.getNameForm(removeClass); if (nf != null) List<NameForm> mappedForms = schema.getNameForm(removeClass); if (mappedForms != null) { StringBuilder buffer = new StringBuilder(); for(NameForm nf : mappedForms) { buffer.append(nf.getNameOrOID()); buffer.append("\t"); } Message message = ERR_SCHEMA_MODIFY_REMOVE_OC_IN_NF.get( removeClass.getNameOrOID(), nf.getNameOrOID()); removeClass.getNameOrOID(), buffer.toString()); throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); } @@ -2267,15 +2278,6 @@ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); } NameForm existingNFForClass = schema.getNameForm(structuralClass); if ((existingNFForClass != null) && (existingNFForClass != existingNF)) { Message message = ERR_SCHEMA_MODIFY_STRUCTURAL_OC_CONFLICT_FOR_ADD_NF. get(nameForm.getNameOrOID(), structuralClass.getNameOrOID(), existingNFForClass.getNameOrOID()); throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); } for (AttributeType at : nameForm.getRequiredAttributes()) { if (! schema.hasAttributeType(at.getOID())) @@ -3345,12 +3347,15 @@ // is no hierarchical relationship between name forms, we don't need to // worry about ordering. values = new LinkedHashSet<AttributeValue>(); for (NameForm nf : schema.getNameFormsByObjectClass().values()) for (List<NameForm> forms : schema.getNameFormsByObjectClass().values()) { if (schemaFile.equals(nf.getSchemaFile())) for(NameForm nf : forms) { values.add(AttributeValues.create( nameFormsType, nf.getDefinition())); if (schemaFile.equals(nf.getSchemaFile())) { values.add(AttributeValues.create( nameFormsType, nf.getDefinition())); } } } opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -4435,7 +4435,7 @@ * * @return The set of name forms defined in the Directory Server. */ public static ConcurrentHashMap<ObjectClass,NameForm> getNameForms() public static ConcurrentHashMap<ObjectClass,List<NameForm>> getNameForms() { return directoryServer.schema.getNameFormsByObjectClass(); } @@ -4457,15 +4457,15 @@ /** * Retrieves the name form associated with the specified objectclass. * Retrieves the name forms associated with the specified objectclass. * * @param objectClass The objectclass for which to retrieve the associated * name form. * * @return The requested name form, or <CODE>null</CODE> if no such name form * is defined in the schema. * @return The requested name forms, or <CODE>null</CODE> if no such name * form is defined in the schema. */ public static NameForm getNameForm(ObjectClass objectClass) public static List<NameForm> getNameForm(ObjectClass objectClass) { return directoryServer.schema.getNameForm(objectClass); } opendj-sdk/opends/src/server/org/opends/server/types/DirectoryConfig.java
@@ -22,9 +22,10 @@ * CDDL HEADER END * * * Copyright 2006-2008 Sun Microsystems, Inc. * Copyright 2006-2009 Sun Microsystems, Inc. */ package org.opends.server.types; import java.util.List; import org.opends.messages.Message; @@ -658,12 +659,12 @@ /** * Retrieves the set of name forms defined in the Directory Server. * The mapping will be between the structural objectclass and its * corresponding name form. The returned map must not be altered by * the caller. * corresponding name forms. The returned map must not be altered * by the caller. * * @return The set of name forms defined in the Directory Server. */ public static Map<ObjectClass,NameForm> getNameForms() public static Map<ObjectClass,List<NameForm>> getNameForms() { return DirectoryServer.getNameForms(); } @@ -671,16 +672,16 @@ /** * Retrieves the name form associated with the specified structural * objectclass. * Retrieves the list of name forms associated with the specified * structural objectclass. * * @param objectClass The structural objectclass for which to * retrieve the associated name form. * * @return The requested name form, or <CODE>null</CODE> if no such * name form is defined in the schema. * @return The list of requested name forms, or <CODE>null</CODE> * if no such name form is defined in the schema. */ public static NameForm getNameForm(ObjectClass objectClass) public static List<NameForm> getNameForm(ObjectClass objectClass) { return DirectoryServer.getNameForm(objectClass); } opendj-sdk/opends/src/server/org/opends/server/types/Entry.java
@@ -2052,14 +2052,60 @@ ditContentRule = null; } if (! checkAttributesAndObjectClasses(ditContentRule, structuralPolicy, invalidReason)) { return false; } if (validateNameForms) { nameForm = DirectoryServer.getNameForm(structuralClass); if ((nameForm != null) && nameForm.isObsolete()) /** * There may be multiple nameforms registered with this * structural objectclass.However, we need to select only one * of the nameforms and its corresponding DITstructure rule. * We will iterate over all the nameforms and see if atleast * one is acceptable before rejecting the entry. * DITStructureRules corresponding to other non-acceptable * nameforms are not applied. */ List<NameForm> listForms = DirectoryServer.getNameForm(structuralClass); if(listForms != null) { nameForm = null; boolean matchFound = false; boolean obsolete = true; for(int index=0; index <listForms.size(); index++) { NameForm nf = listForms.get(index); if(!nf.isObsolete()) { obsolete = false; matchFound = checkNameForm(nf, structuralPolicy, invalidReason); if(matchFound) { nameForm = nf; break; } if(index != listForms.size()-1) { invalidReason.append(","); } } } if(! obsolete && !matchFound) { //We couldn't match this entry against any of the // nameforms. return false; } } if (validateStructureRules && (nameForm != null)) { ditStructureRule = @@ -2074,24 +2120,6 @@ } if (! checkAttributesAndObjectClasses(ditContentRule, structuralPolicy, invalidReason)) { return false; } // If there is a name form for this entry, then make sure that the // RDN for the entry is in compliance with it. if (nameForm != null) { if (! checkNameForm(nameForm, structuralPolicy, invalidReason)) { return false; } } // If there is a DIT content rule for this entry, then make sure // that the entry is in compliance with it. if (ditContentRule != null) @@ -2304,54 +2332,54 @@ RDN rdn = dn.getRDN(); if (rdn != null) { // Make sure that all the required attributes are present. for (AttributeType t : nameForm.getRequiredAttributes()) { if (! rdn.hasAttributeType(t)) // Make sure that all the required attributes are present. for (AttributeType t : nameForm.getRequiredAttributes()) { Message message = ERR_ENTRY_SCHEMA_RDN_MISSING_REQUIRED_ATTR.get( String.valueOf(dn), t.getNameOrOID(), nameForm.getNameOrOID()); if (! rdn.hasAttributeType(t)) { Message message = ERR_ENTRY_SCHEMA_RDN_MISSING_REQUIRED_ATTR.get( String.valueOf(dn), t.getNameOrOID(), nameForm.getNameOrOID()); if (structuralPolicy == AcceptRejectWarn.REJECT) { invalidReason.append(message); return false; if (structuralPolicy == AcceptRejectWarn.REJECT) { invalidReason.append(message); return false; } else if (structuralPolicy == AcceptRejectWarn.WARN) { logError(message); } } } else if (structuralPolicy == AcceptRejectWarn.WARN) { logError(message); } } } // Make sure that all attributes in the RDN are allowed. int numAVAs = rdn.getNumValues(); for (int i = 0; i < numAVAs; i++) { AttributeType t = rdn.getAttributeType(i); if (! nameForm.isRequiredOrOptional(t)) { Message message = ERR_ENTRY_SCHEMA_RDN_DISALLOWED_ATTR.get( String.valueOf(dn), t.getNameOrOID(), nameForm.getNameOrOID()); // Make sure that all attributes in the RDN are allowed. int numAVAs = rdn.getNumValues(); for (int i = 0; i < numAVAs; i++) { AttributeType t = rdn.getAttributeType(i); if (! nameForm.isRequiredOrOptional(t)) { Message message = ERR_ENTRY_SCHEMA_RDN_DISALLOWED_ATTR.get( String.valueOf(dn), t.getNameOrOID(), nameForm.getNameOrOID()); if (structuralPolicy == AcceptRejectWarn.REJECT) { invalidReason.append(message); return false; if (structuralPolicy == AcceptRejectWarn.REJECT) { invalidReason.append(message); return false; } else if (structuralPolicy == AcceptRejectWarn.WARN) { logError(message); } } } } else if (structuralPolicy == AcceptRejectWarn.WARN) { logError(message); } } } } // If we've gotten here, then things are OK. return true; @@ -2707,27 +2735,33 @@ } else { NameForm parentNF = List<NameForm> allNFs = DirectoryServer.getNameForm(parentStructuralClass); if ((parentNF != null) && (! parentNF.isObsolete())) if(allNFs != null) { DITStructureRule parentDSR = DirectoryServer.getDITStructureRule(parentNF); if ((parentDSR != null) && (! parentDSR.isObsolete())) for(NameForm parentNF : allNFs) { Message message = ERR_ENTRY_SCHEMA_VIOLATES_PARENT_DSR.get( String.valueOf(dn), String.valueOf(parentEntry.getDN())); if ((parentNF != null) && (! parentNF.isObsolete())) { DITStructureRule parentDSR = DirectoryServer.getDITStructureRule(parentNF); if ((parentDSR != null) && (! parentDSR.isObsolete())) { Message message = ERR_ENTRY_SCHEMA_VIOLATES_PARENT_DSR.get( String.valueOf(dn), String.valueOf(parentEntry.getDN())); if (structuralPolicy == AcceptRejectWarn.REJECT) { invalidReason.append(message); return false; } else if (structuralPolicy == AcceptRejectWarn.WARN) { logError(message); if (structuralPolicy == AcceptRejectWarn.REJECT) { invalidReason.append(message); return false; } else if (structuralPolicy == AcceptRejectWarn.WARN) { logError(message); } } } } } opendj-sdk/opends/src/server/org/opends/server/types/Schema.java
@@ -34,6 +34,7 @@ import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashSet; @@ -180,9 +181,10 @@ ditStructureRulesByNameForm; // The set of name forms for this schema, mapped between the // structural objectclass for the definition and the name form // itself. private ConcurrentHashMap<ObjectClass,NameForm> nameFormsByOC; // structural objectclass for the definition and the list of name // forms private ConcurrentHashMap<ObjectClass,List<NameForm>> nameFormsByOC; // The set of name forms for this schema, mapped between the // names/OID and the name form itself. @@ -258,7 +260,8 @@ new ConcurrentHashMap<Integer,DITStructureRule>(); ditStructureRulesByNameForm = new ConcurrentHashMap<NameForm,DITStructureRule>(); nameFormsByOC = new ConcurrentHashMap<ObjectClass,NameForm>(); nameFormsByOC = new ConcurrentHashMap<ObjectClass,List<NameForm>>(); nameFormsByName = new ConcurrentHashMap<String,NameForm>(); subordinateTypes = new ConcurrentHashMap<AttributeType,List<AttributeType>>(); @@ -2590,14 +2593,12 @@ /** * Retrieves the name form definitions for this schema, as a mapping * between the objectclass for the name form and the name form * itself. Each name form should only be present once, since its * only key is its objectclass. The contents of the returned * mapping must not be altered. * between the objectclass for the name forms and the name forms * themselves. * * @return The name form definitions for this schema. */ public ConcurrentHashMap<ObjectClass,NameForm> public ConcurrentHashMap<ObjectClass,List<NameForm>> getNameFormsByObjectClass() { return nameFormsByOC; @@ -2657,15 +2658,17 @@ /** * Retrieves the name form definition for the specified objectclass. * Retrieves the name forms definition for the specified * objectclass. * * @param objectClass The objectclass for the name form to * retrieve. * * @return The requested name form, or <CODE>null</CODE> if no name * form is registered with the provided objectClass. * @return The requested name forms, or <CODE>null</CODE> if no * name forms are registered with the provided * objectClass. */ public NameForm getNameForm(ObjectClass objectClass) public List<NameForm> getNameForm(ObjectClass objectClass) { return nameFormsByOC.get(objectClass); } @@ -2708,19 +2711,25 @@ synchronized (nameFormsByOC) { ObjectClass objectClass = nameForm.getStructuralClass(); List<NameForm> mappedForms = nameFormsByOC.get(objectClass); if (! overwriteExisting) { if (nameFormsByOC.containsKey(objectClass)) if(mappedForms !=null) { NameForm conflictingNameForm = nameFormsByOC.get(objectClass); Message message = ERR_SCHEMA_CONFLICTING_NAME_FORM_OC. get(nameForm.getNameOrOID(), objectClass.getNameOrOID(), conflictingNameForm.getNameOrOID()); throw new DirectoryException( ResultCode.CONSTRAINT_VIOLATION, message); //Iterate over the forms to make sure we aren't adding a //duplicate. for(NameForm nf : mappedForms) { if(nf.equals(nameForm)) { Message message = ERR_SCHEMA_CONFLICTING_NAME_FORM_OC. get(nameForm.getNameOrOID(), objectClass.getNameOrOID(), nf.getNameOrOID()); throw new DirectoryException( ResultCode.CONSTRAINT_VIOLATION, message); } } } String oid = toLowerCase(nameForm.getOID()); @@ -2750,7 +2759,13 @@ } } nameFormsByOC.put(objectClass, nameForm); if(mappedForms == null) { mappedForms = new ArrayList<NameForm>(); } mappedForms.add(nameForm); nameFormsByOC.put(objectClass, mappedForms); nameFormsByName.put(toLowerCase(nameForm.getOID()), nameForm); for (String name : nameForm.getNames().keySet()) @@ -2781,6 +2796,16 @@ { synchronized (nameFormsByOC) { List<NameForm> mappedForms = nameFormsByOC.get( nameForm.getStructuralClass()); if(mappedForms != null) { mappedForms.remove(nameForm); if(mappedForms.size() == 0) { nameFormsByOC.remove(nameForm.getStructuralClass()); } } nameFormsByOC.remove(nameForm.getStructuralClass(), nameForm); nameFormsByName.remove(toLowerCase(nameForm.getOID()), nameForm); @@ -3006,15 +3031,18 @@ } } for (NameForm nf : nameFormsByOC.values()) for (List<NameForm> mappedForms : nameFormsByOC.values()) { if (nf.getRequiredAttributes().contains(t) || nf.getOptionalAttributes().contains(t)) for(NameForm nf : mappedForms) { NameForm newNF = nf.recreateFromDefinition(); deregisterNameForm(nf); registerNameForm(newNF, true); rebuildDependentElements(nf, depth+1); if (nf.getRequiredAttributes().contains(t) || nf.getOptionalAttributes().contains(t)) { NameForm newNF = nf.recreateFromDefinition(); deregisterNameForm(nf); registerNameForm(newNF, true); rebuildDependentElements(nf, depth+1); } } } @@ -3058,13 +3086,19 @@ } } NameForm nf = nameFormsByOC.get(c); if (nf != null) List<NameForm> mappedForms = nameFormsByOC.get(c); if(mappedForms != null) { NameForm newNF = nf.recreateFromDefinition(); deregisterNameForm(nf); registerNameForm(newNF, true); rebuildDependentElements(nf, depth+1); for(NameForm nf : mappedForms) { if (nf != null) { NameForm newNF = nf.recreateFromDefinition(); deregisterNameForm(nf); registerNameForm(newNF, true); rebuildDependentElements(nf, depth+1); } } } for (DITContentRule dcr : ditContentRules.values()) opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/SchemaBackendTestCase.java
@@ -22,7 +22,7 @@ * CDDL HEADER END * * * Copyright 2006-2008 Sun Microsystems, Inc. * Copyright 2006-2009 Sun Microsystems, Inc. */ package org.opends.server.backends; @@ -2923,8 +2923,8 @@ "-f", path }; assertFalse(LDAPModify.mainModify(args, false, null, null) == 0); assertFalse(DirectoryServer.getSchema().hasNameForm(nameFormName)); assertTrue(LDAPModify.mainModify(args, false, null, null) == 0); assertTrue(DirectoryServer.getSchema().hasNameForm(nameFormName)); } @@ -5405,7 +5405,7 @@ { File tempFile = File.createTempFile("schema", "testImportLDIF"); tempFile.deleteOnExit(); LDIFExportConfig exportConfig = new LDIFExportConfig(tempFile.getAbsolutePath(), ExistingFileBehavior.OVERWRITE); @@ -5414,7 +5414,7 @@ LDIFImportConfig importConfig = new LDIFImportConfig(tempFile.getAbsolutePath()); schemaBackend.importLDIF(importConfig); }