001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020 package org.apache.directory.server.core.schema.registries.synchronizers; 021 022 023 import java.util.ArrayList; 024 import java.util.List; 025 026 import org.apache.directory.server.core.interceptor.context.ModifyOperationContext; 027 import org.apache.directory.server.i18n.I18n; 028 import org.apache.directory.shared.ldap.constants.MetaSchemaConstants; 029 import org.apache.directory.shared.ldap.constants.SchemaConstants; 030 import org.apache.directory.shared.ldap.entry.ServerEntry; 031 import org.apache.directory.shared.ldap.exception.LdapException; 032 import org.apache.directory.shared.ldap.exception.LdapInvalidDnException; 033 import org.apache.directory.shared.ldap.exception.LdapSchemaViolationException; 034 import org.apache.directory.shared.ldap.exception.LdapUnwillingToPerformException; 035 import org.apache.directory.shared.ldap.message.ResultCodeEnum; 036 import org.apache.directory.shared.ldap.name.DN; 037 import org.apache.directory.shared.ldap.name.RDN; 038 import org.apache.directory.shared.ldap.schema.LdapComparator; 039 import org.apache.directory.shared.ldap.schema.SchemaManager; 040 import org.apache.directory.shared.ldap.schema.registries.Schema; 041 import org.apache.directory.shared.ldap.util.StringTools; 042 import org.slf4j.Logger; 043 import org.slf4j.LoggerFactory; 044 045 046 /** 047 * A handler for operations performed to add, delete, modify, rename and 048 * move schema comparators. 049 * 050 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 051 * @version $Rev$, $Date$ 052 */ 053 public class ComparatorSynchronizer extends AbstractRegistrySynchronizer 054 { 055 /** A logger for this class */ 056 private static final Logger LOG = LoggerFactory.getLogger( ComparatorSynchronizer.class ); 057 058 059 /** 060 * Creates a new instance of ComparatorSynchronizer. 061 * 062 * @param schemaManager The global schemaManager 063 * @throws Exception If the initialization failed 064 */ 065 public ComparatorSynchronizer( SchemaManager schemaManager ) throws Exception 066 { 067 super( schemaManager ); 068 } 069 070 071 /** 072 * {@inheritDoc} 073 */ 074 public boolean modify( ModifyOperationContext opContext, ServerEntry targetEntry, boolean cascade ) 075 throws Exception 076 { 077 DN name = opContext.getDn(); 078 ServerEntry entry = opContext.getEntry(); 079 String schemaName = getSchemaName( name ); 080 String oid = getOid( entry ); 081 LdapComparator<?> comparator = factory.getLdapComparator( schemaManager, targetEntry, schemaManager 082 .getRegistries(), schemaName ); 083 084 if ( isSchemaEnabled( schemaName ) ) 085 { 086 comparator.setSchemaName( schemaName ); 087 088 schemaManager.unregisterComparator( oid ); 089 schemaManager.add( comparator ); 090 091 return SCHEMA_MODIFIED; 092 } 093 094 return SCHEMA_UNCHANGED; 095 } 096 097 098 /** 099 * {@inheritDoc} 100 */ 101 public void add( ServerEntry entry ) throws Exception 102 { 103 DN dn = entry.getDn(); 104 DN parentDn = ( DN ) dn.clone(); 105 parentDn.remove( parentDn.size() - 1 ); 106 107 // The parent DN must be ou=comparators,cn=<schemaName>,ou=schema 108 checkParent( parentDn, schemaManager, SchemaConstants.COMPARATOR ); 109 110 // The new schemaObject's OID must not already exist 111 checkOidIsUniqueForComparator( entry ); 112 113 // Build the new Comparator from the given entry 114 String schemaName = getSchemaName( dn ); 115 116 LdapComparator<?> comparator = factory.getLdapComparator( schemaManager, entry, schemaManager.getRegistries(), 117 schemaName ); 118 119 // At this point, the constructed LdapComparator has not been checked against the 120 // existing Registries. It will be checked there, if the schema and the 121 // LdapComparator are both enabled. 122 Schema schema = schemaManager.getLoadedSchema( schemaName ); 123 124 if ( schema.isEnabled() && comparator.isEnabled() ) 125 { 126 if ( schemaManager.add( comparator ) ) 127 { 128 LOG.debug( "Added {} into the enabled schema {}", dn.getName(), schemaName ); 129 } 130 else 131 { 132 // We have some error : reject the addition and get out 133 String msg = I18n.err( I18n.ERR_350, entry.getDn().getName(), StringTools.listToString( 134 schemaManager.getErrors() ) ); 135 LOG.info( msg ); 136 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg ); 137 } 138 } 139 else 140 { 141 LOG.debug( "The Comparator {} cannot be added in the disabled schema {}", dn.getName(), schemaName ); 142 } 143 } 144 145 146 /** 147 * {@inheritDoc} 148 */ 149 public void delete( ServerEntry entry, boolean cascade ) throws Exception 150 { 151 DN dn = entry.getDn(); 152 DN parentDn = ( DN ) dn.clone(); 153 parentDn.remove( parentDn.size() - 1 ); 154 155 // The parent DN must be ou=comparators,cn=<schemaName>,ou=schema 156 checkParent( parentDn, schemaManager, SchemaConstants.COMPARATOR ); 157 158 // Get the SchemaName 159 String schemaName = getSchemaName( entry.getDn() ); 160 161 // Get the Schema 162 Schema schema = schemaManager.getLoadedSchema( schemaName ); 163 164 if ( schema.isDisabled() ) 165 { 166 // The schema is disabled, nothing to do. 167 LOG.debug( "The Comparator {} cannot be deleted from the disabled schema {}", dn.getName(), schemaName ); 168 169 return; 170 } 171 172 // Test that the Oid exists 173 LdapComparator<?> comparator = null; 174 175 try 176 { 177 comparator = ( LdapComparator<?> ) checkComparatorOidExists( entry ); 178 } 179 catch ( LdapSchemaViolationException lsve ) 180 { 181 // The comparator does not exist 182 comparator = factory.getLdapComparator( schemaManager, entry, schemaManager.getRegistries(), schemaName ); 183 184 if ( schemaManager.getRegistries().contains( comparator ) ) 185 { 186 // Remove the Comparator from the schema/SchemaObject Map 187 schemaManager.getRegistries().dissociateFromSchema( comparator ); 188 189 // Ok, we can exit. 190 return; 191 } 192 else 193 { 194 // Ok, definitively an error 195 String msg = I18n.err( I18n.ERR_351, entry.getDn().getName() ); 196 LOG.info( msg ); 197 throw new LdapSchemaViolationException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg ); 198 } 199 } 200 201 List<Throwable> errors = new ArrayList<Throwable>(); 202 203 if ( schema.isEnabled() && comparator.isEnabled() ) 204 { 205 if ( schemaManager.delete( comparator ) ) 206 { 207 LOG.debug( "Deleted {} from the enabled schema {}", dn.getName(), schemaName ); 208 } 209 else 210 { 211 String msg = I18n.err( I18n.ERR_352, entry.getDn().getName(), StringTools.listToString( 212 errors ) ); 213 LOG.info( msg ); 214 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg ); 215 } 216 } 217 else 218 { 219 LOG.debug( "The Comparator {} cannot be deleted from the disabled schema {}", dn.getName(), schemaName ); 220 } 221 } 222 223 224 /** 225 * {@inheritDoc} 226 */ 227 public void rename( ServerEntry entry, RDN newRdn, boolean cascade ) throws Exception 228 { 229 String oldOid = getOid( entry ); 230 231 if ( schemaManager.getMatchingRuleRegistry().contains( oldOid ) ) 232 { 233 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, 234 I18n.err( I18n.ERR_353, oldOid ) ); 235 } 236 237 String oid = ( String ) newRdn.getNormValue(); 238 checkOidIsUniqueForComparator( oid ); 239 240 String schemaName = getSchemaName( entry.getDn() ); 241 242 if ( isSchemaEnabled( schemaName ) ) 243 { 244 // Inject the new OID in the entry 245 ServerEntry targetEntry = ( ServerEntry ) entry.clone(); 246 String newOid = ( String ) newRdn.getNormValue(); 247 checkOidIsUnique( newOid ); 248 targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid ); 249 250 // Inject the new DN 251 DN newDn = new DN( targetEntry.getDn() ); 252 newDn.remove( newDn.size() - 1 ); 253 newDn.add( newRdn ); 254 targetEntry.setDn( newDn ); 255 256 // Register the new comparator, and unregister the old one 257 LdapComparator<?> comparator = factory.getLdapComparator( schemaManager, targetEntry, schemaManager 258 .getRegistries(), schemaName ); 259 schemaManager.unregisterComparator( oldOid ); 260 schemaManager.add( comparator ); 261 } 262 } 263 264 265 public void moveAndRename( DN oriChildName, DN newParentName, RDN newRdn, boolean deleteOldRn, 266 ServerEntry entry, boolean cascade ) throws Exception 267 { 268 checkNewParent( newParentName ); 269 String oldOid = getOid( entry ); 270 271 if ( schemaManager.getMatchingRuleRegistry().contains( oldOid ) ) 272 { 273 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, 274 I18n.err( I18n.ERR_353, oldOid ) ); 275 } 276 277 String oid = ( String ) newRdn.getNormValue(); 278 checkOidIsUniqueForComparator( oid ); 279 280 String newSchemaName = getSchemaName( newParentName ); 281 282 LdapComparator<?> comparator = factory.getLdapComparator( schemaManager, entry, schemaManager.getRegistries(), 283 newSchemaName ); 284 285 String oldSchemaName = getSchemaName( oriChildName ); 286 287 if ( isSchemaEnabled( oldSchemaName ) ) 288 { 289 schemaManager.unregisterComparator( oldOid ); 290 } 291 292 if ( isSchemaEnabled( newSchemaName ) ) 293 { 294 schemaManager.add( comparator ); 295 } 296 } 297 298 299 public void move( DN oriChildName, DN newParentName, ServerEntry entry, boolean cascade ) throws Exception 300 { 301 checkNewParent( newParentName ); 302 String oid = getOid( entry ); 303 304 if ( schemaManager.getMatchingRuleRegistry().contains( oid ) ) 305 { 306 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, 307 I18n.err( I18n.ERR_354, oid ) ); 308 } 309 310 String newSchemaName = getSchemaName( newParentName ); 311 312 LdapComparator<?> comparator = factory.getLdapComparator( schemaManager, entry, schemaManager.getRegistries(), 313 newSchemaName ); 314 315 String oldSchemaName = getSchemaName( oriChildName ); 316 317 if ( isSchemaEnabled( oldSchemaName ) ) 318 { 319 schemaManager.unregisterComparator( oid ); 320 } 321 322 if ( isSchemaEnabled( newSchemaName ) ) 323 { 324 schemaManager.add( comparator ); 325 } 326 } 327 328 329 private void checkOidIsUniqueForComparator( String oid ) throws LdapSchemaViolationException 330 { 331 if ( schemaManager.getComparatorRegistry().contains( oid ) ) 332 { 333 throw new LdapSchemaViolationException( ResultCodeEnum.OTHER, 334 I18n.err( I18n.ERR_355, oid ) ); 335 } 336 } 337 338 339 private void checkOidIsUniqueForComparator( ServerEntry entry ) throws Exception 340 { 341 String oid = getOid( entry ); 342 343 if ( schemaManager.getComparatorRegistry().contains( oid ) ) 344 { 345 throw new LdapSchemaViolationException( ResultCodeEnum.OTHER, 346 I18n.err( I18n.ERR_355, oid ) ); 347 } 348 } 349 350 351 /** 352 * Check that a Comparator exists in the ComparatorRegistry, and if so, 353 * return it. 354 */ 355 protected LdapComparator<?> checkComparatorOidExists( ServerEntry entry ) throws Exception 356 { 357 String oid = getOid( entry ); 358 359 if ( schemaManager.getComparatorRegistry().contains( oid ) ) 360 { 361 return ( LdapComparator<?> ) schemaManager.getComparatorRegistry().get( oid ); 362 } 363 else 364 { 365 throw new LdapSchemaViolationException( ResultCodeEnum.OTHER, 366 I18n.err( I18n.ERR_336, oid ) ); 367 } 368 } 369 370 371 private void checkNewParent( DN newParent ) throws LdapException 372 { 373 if ( newParent.size() != 3 ) 374 { 375 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION, 376 I18n.err( I18n.ERR_357 ) ); 377 } 378 379 RDN rdn = newParent.getRdn(); 380 381 if ( !schemaManager.getAttributeTypeRegistry().getOidByName( rdn.getNormType() ).equals( 382 SchemaConstants.OU_AT_OID ) ) 383 { 384 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION, I18n.err( I18n.ERR_358 ) ); 385 } 386 387 if ( !( ( String ) rdn.getNormValue() ).equalsIgnoreCase( SchemaConstants.COMPARATORS_AT ) ) 388 { 389 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION, I18n.err( I18n.ERR_359 ) ); 390 } 391 } 392 }