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 org.apache.directory.server.core.interceptor.context.ModifyOperationContext; 024 import org.apache.directory.server.i18n.I18n; 025 import org.apache.directory.shared.ldap.constants.MetaSchemaConstants; 026 import org.apache.directory.shared.ldap.constants.SchemaConstants; 027 import org.apache.directory.shared.ldap.entry.ServerEntry; 028 import org.apache.directory.shared.ldap.exception.LdapException; 029 import org.apache.directory.shared.ldap.exception.LdapInvalidDnException; 030 import org.apache.directory.shared.ldap.exception.LdapSchemaViolationException; 031 import org.apache.directory.shared.ldap.exception.LdapUnwillingToPerformException; 032 import org.apache.directory.shared.ldap.message.ResultCodeEnum; 033 import org.apache.directory.shared.ldap.name.DN; 034 import org.apache.directory.shared.ldap.name.RDN; 035 import org.apache.directory.shared.ldap.schema.SchemaManager; 036 import org.apache.directory.shared.ldap.schema.SyntaxChecker; 037 import org.apache.directory.shared.ldap.schema.registries.Registries; 038 import org.apache.directory.shared.ldap.schema.registries.Schema; 039 import org.apache.directory.shared.ldap.util.StringTools; 040 import org.slf4j.Logger; 041 import org.slf4j.LoggerFactory; 042 043 044 /** 045 * A synchronizer which detects changes to syntaxCheckers and updates the 046 * respective {@link Registries}. 047 * 048 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 049 * @version $Rev$, $Date$ 050 */ 051 public class SyntaxCheckerSynchronizer extends AbstractRegistrySynchronizer 052 { 053 /** A logger for this class */ 054 private static final Logger LOG = LoggerFactory.getLogger( SyntaxCheckerSynchronizer.class ); 055 056 057 /** 058 * Creates a new instance of SyntaxCheckerSynchronizer. 059 * 060 * @param schemaManager The global schemaManager 061 * @throws Exception If the initialization failed 062 */ 063 public SyntaxCheckerSynchronizer( SchemaManager schemaManager ) throws Exception 064 { 065 super( schemaManager ); 066 } 067 068 069 /** 070 * {@inheritDoc} 071 */ 072 public boolean modify( ModifyOperationContext opContext, ServerEntry targetEntry, boolean cascade ) 073 throws Exception 074 { 075 DN name = opContext.getDn(); 076 ServerEntry entry = opContext.getEntry(); 077 String schemaName = getSchemaName( name ); 078 String oid = getOid( entry ); 079 SyntaxChecker syntaxChecker = factory.getSyntaxChecker( schemaManager, targetEntry, schemaManager 080 .getRegistries(), schemaName ); 081 082 if ( isSchemaEnabled( schemaName ) ) 083 { 084 syntaxChecker.setSchemaName( schemaName ); 085 086 schemaManager.unregisterSyntaxChecker( oid ); 087 schemaManager.add( syntaxChecker ); 088 089 return SCHEMA_MODIFIED; 090 } 091 092 return SCHEMA_UNCHANGED; 093 } 094 095 096 /** 097 * {@inheritDoc} 098 */ 099 public void add( ServerEntry entry ) throws Exception 100 { 101 DN dn = entry.getDn(); 102 DN parentDn = ( DN ) dn.clone(); 103 parentDn.remove( parentDn.size() - 1 ); 104 105 // The parent DN must be ou=syntaxcheckers,cn=<schemaName>,ou=schema 106 checkParent( parentDn, schemaManager, SchemaConstants.SYNTAX_CHECKER ); 107 108 // The new schemaObject's OID must not already exist 109 checkOidIsUniqueForSyntaxChecker( entry ); 110 111 // Build the new SyntaxChecker from the given entry 112 String schemaName = getSchemaName( dn ); 113 114 SyntaxChecker syntaxChecker = factory.getSyntaxChecker( schemaManager, entry, schemaManager.getRegistries(), 115 schemaName ); 116 117 // At this point, the constructed SyntaxChecker has not been checked against the 118 // existing Registries. It will be checked there, if the schema and the 119 // SyntaxChecker are both enabled. 120 Schema schema = schemaManager.getLoadedSchema( schemaName ); 121 122 if ( schema.isEnabled() && syntaxChecker.isEnabled() ) 123 { 124 if ( schemaManager.add( syntaxChecker ) ) 125 { 126 LOG.debug( "Added {} into the enabled schema {}", dn.getName(), schemaName ); 127 } 128 else 129 { 130 String msg = I18n.err( I18n.ERR_386, entry.getDn().getName(), 131 StringTools.listToString( schemaManager.getErrors() ) ); 132 LOG.info( msg ); 133 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg ); 134 } 135 } 136 else 137 { 138 LOG.debug( "The SyntaxChecker {} cannot be added in the disabled schema {}", dn.getName(), schemaName ); 139 } 140 } 141 142 143 /** 144 * {@inheritDoc} 145 */ 146 public void delete( ServerEntry entry, boolean cascade ) throws Exception 147 { 148 DN dn = entry.getDn(); 149 DN parentDn = ( DN ) dn.clone(); 150 parentDn.remove( parentDn.size() - 1 ); 151 152 // The parent DN must be ou=syntaxcheckers,cn=<schemaName>,ou=schema 153 checkParent( parentDn, schemaManager, SchemaConstants.SYNTAX_CHECKER ); 154 155 // Get the SyntaxChecker's instance 156 String schemaName = getSchemaName( entry.getDn() ); 157 158 // Get the Schema 159 Schema schema = schemaManager.getLoadedSchema( schemaName ); 160 161 if ( schema.isDisabled() ) 162 { 163 // The schema is disabled, nothing to do. 164 LOG.debug( "The SyntaxChecker {} cannot be deleted from the disabled schema {}", dn.getName(), schemaName ); 165 166 return; 167 } 168 169 // Test that the Oid exists 170 SyntaxChecker syntaxChecker = null; 171 172 try 173 { 174 syntaxChecker = ( SyntaxChecker ) checkSyntaxCheckerOidExists( entry ); 175 } 176 catch ( LdapSchemaViolationException lsve ) 177 { 178 // The syntaxChecker does not exist 179 syntaxChecker = factory.getSyntaxChecker( schemaManager, entry, schemaManager.getRegistries(), schemaName ); 180 181 if ( schemaManager.getRegistries().contains( syntaxChecker ) ) 182 { 183 // Remove the syntaxChecker from the schema/SchemaObject Map 184 schemaManager.getRegistries().dissociateFromSchema( syntaxChecker ); 185 186 // Ok, we can exit. 187 return; 188 } 189 else 190 { 191 // Ok, definitively an error 192 String msg = I18n.err( I18n.ERR_387, entry.getDn().getName() ); 193 LOG.info( msg ); 194 throw new LdapSchemaViolationException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg ); 195 } 196 } 197 198 if ( schema.isEnabled() && syntaxChecker.isEnabled() ) 199 { 200 if ( schemaManager.delete( syntaxChecker ) ) 201 { 202 LOG.debug( "Deleted {} from the enabled schema {}", dn.getName(), schemaName ); 203 } 204 else 205 { 206 String msg = I18n.err( I18n.ERR_386, entry.getDn().getName(), 207 StringTools.listToString( schemaManager.getErrors() ) ); 208 LOG.info( msg ); 209 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg ); 210 } 211 } 212 else 213 { 214 LOG.debug( "The syntaxChecker {} cannot be deleted from the disabled schema {}", dn.getName(), schemaName ); 215 } 216 } 217 218 219 /** 220 * {@inheritDoc} 221 */ 222 public void rename( ServerEntry entry, RDN newRdn, boolean cascade ) throws Exception 223 { 224 String oldOid = getOid( entry ); 225 String schemaName = getSchemaName( entry.getDn() ); 226 227 if ( schemaManager.getLdapSyntaxRegistry().contains( oldOid ) ) 228 { 229 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, 230 I18n.err( I18n.ERR_389, oldOid ) ); 231 } 232 233 ServerEntry targetEntry = ( ServerEntry ) entry.clone(); 234 String newOid = ( String ) newRdn.getNormValue(); 235 236 if ( schemaManager.getSyntaxCheckerRegistry().contains( newOid ) ) 237 { 238 throw new LdapSchemaViolationException( ResultCodeEnum.OTHER, 239 I18n.err( I18n.ERR_390, newOid ) ); 240 } 241 242 targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid ); 243 244 if ( isSchemaEnabled( schemaName ) ) 245 { 246 SyntaxChecker syntaxChecker = factory.getSyntaxChecker( schemaManager, targetEntry, schemaManager 247 .getRegistries(), schemaName ); 248 schemaManager.unregisterSyntaxChecker( oldOid ); 249 schemaManager.add( syntaxChecker ); 250 } 251 } 252 253 254 public void moveAndRename( DN oriChildName, DN newParentName, RDN newRdn, boolean deleteOldRn, 255 ServerEntry entry, boolean cascade ) throws Exception 256 { 257 checkNewParent( newParentName ); 258 String oldOid = getOid( entry ); 259 String oldSchemaName = getSchemaName( oriChildName ); 260 String newSchemaName = getSchemaName( newParentName ); 261 262 if ( schemaManager.getLdapSyntaxRegistry().contains( oldOid ) ) 263 { 264 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, 265 I18n.err( I18n.ERR_391, oldOid ) ); 266 } 267 268 ServerEntry targetEntry = ( ServerEntry ) entry.clone(); 269 270 String newOid = ( String ) newRdn.getNormValue(); 271 272 if ( schemaManager.getSyntaxCheckerRegistry().contains( newOid ) ) 273 { 274 throw new LdapSchemaViolationException( ResultCodeEnum.OTHER, 275 I18n.err( I18n.ERR_390, newOid ) ); 276 } 277 278 targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid ); 279 SyntaxChecker syntaxChecker = factory.getSyntaxChecker( schemaManager, targetEntry, schemaManager 280 .getRegistries(), newSchemaName ); 281 282 if ( isSchemaEnabled( oldSchemaName ) ) 283 { 284 schemaManager.unregisterSyntaxChecker( oldOid ); 285 } 286 287 if ( isSchemaEnabled( newSchemaName ) ) 288 { 289 schemaManager.add( syntaxChecker ); 290 } 291 } 292 293 294 public void move( DN oriChildName, DN newParentName, ServerEntry entry, boolean cascade ) throws Exception 295 { 296 checkNewParent( newParentName ); 297 String oid = getOid( entry ); 298 String oldSchemaName = getSchemaName( oriChildName ); 299 String newSchemaName = getSchemaName( newParentName ); 300 301 if ( schemaManager.getLdapSyntaxRegistry().contains( oid ) ) 302 { 303 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, 304 I18n.err( I18n.ERR_393, oid ) ); 305 } 306 307 SyntaxChecker syntaxChecker = factory.getSyntaxChecker( schemaManager, entry, schemaManager.getRegistries(), 308 newSchemaName ); 309 310 if ( isSchemaEnabled( oldSchemaName ) ) 311 { 312 schemaManager.unregisterSyntaxChecker( oid ); 313 } 314 315 if ( isSchemaEnabled( newSchemaName ) ) 316 { 317 schemaManager.add( syntaxChecker ); 318 } 319 } 320 321 322 private void checkOidIsUniqueForSyntaxChecker( ServerEntry entry ) throws Exception 323 { 324 String oid = getOid( entry ); 325 326 if ( schemaManager.getNormalizerRegistry().contains( oid ) ) 327 { 328 throw new LdapSchemaViolationException( ResultCodeEnum.OTHER, 329 I18n.err( I18n.ERR_390, oid ) ); 330 } 331 } 332 333 334 /** 335 * Check that a SyntaxChecker exists in the SyntaxCheckerRegistry, and if so, 336 * return it. 337 */ 338 protected SyntaxChecker checkSyntaxCheckerOidExists( ServerEntry entry ) throws Exception 339 { 340 String oid = getOid( entry ); 341 342 if ( schemaManager.getSyntaxCheckerRegistry().contains( oid ) ) 343 { 344 return (SyntaxChecker)schemaManager.getSyntaxCheckerRegistry().get( oid ); 345 } 346 else 347 { 348 throw new LdapSchemaViolationException( ResultCodeEnum.OTHER, 349 I18n.err( I18n.ERR_336, oid ) ); 350 } 351 } 352 353 354 private void checkNewParent( DN newParent ) throws LdapException 355 { 356 if ( newParent.size() != 3 ) 357 { 358 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION, 359 I18n.err( I18n.ERR_396 ) ); 360 } 361 362 RDN rdn = newParent.getRdn(); 363 if ( !schemaManager.getAttributeTypeRegistry().getOidByName( rdn.getNormType() ).equals( 364 SchemaConstants.OU_AT_OID ) ) 365 { 366 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION, 367 I18n.err( I18n.ERR_397 ) ); 368 } 369 370 if ( !( ( String ) rdn.getNormValue() ).equalsIgnoreCase( SchemaConstants.SYNTAX_CHECKERS_AT ) ) 371 { 372 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION, 373 I18n.err( I18n.ERR_372 ) ); 374 } 375 } 376 }