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.Normalizer; 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 * 048 * 049 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 050 * @version $Rev$, $Date$ 051 */ 052 public class NormalizerSynchronizer extends AbstractRegistrySynchronizer 053 { 054 /** A logger for this class */ 055 private static final Logger LOG = LoggerFactory.getLogger( NormalizerSynchronizer.class ); 056 057 058 /** 059 * Creates a new instance of NormalizerSynchronizer. 060 * 061 * @param registries The global registries 062 * @throws Exception If the initialization failed 063 */ 064 public NormalizerSynchronizer( SchemaManager schemaManager ) throws Exception 065 { 066 super( schemaManager ); 067 } 068 069 070 /** 071 * {@inheritDoc} 072 */ 073 public boolean modify( ModifyOperationContext opContext, ServerEntry targetEntry, boolean cascade ) 074 throws Exception 075 { 076 DN name = opContext.getDn(); 077 ServerEntry entry = opContext.getEntry(); 078 String schemaName = getSchemaName( name ); 079 String oldOid = getOid( entry ); 080 Normalizer normalizer = factory.getNormalizer( schemaManager, targetEntry, schemaManager.getRegistries(), 081 schemaName ); 082 083 if ( isSchemaEnabled( schemaName ) ) 084 { 085 normalizer.setSchemaName( schemaName ); 086 087 schemaManager.unregisterNormalizer( oldOid ); 088 schemaManager.add( normalizer ); 089 090 return SCHEMA_MODIFIED; 091 } 092 093 return SCHEMA_UNCHANGED; 094 } 095 096 097 /** 098 * {@inheritDoc} 099 */ 100 public void add( ServerEntry entry ) throws Exception 101 { 102 DN dn = entry.getDn(); 103 DN parentDn = ( DN ) dn.clone(); 104 parentDn.remove( parentDn.size() - 1 ); 105 106 // The parent DN must be ou=normalizers,cn=<schemaName>,ou=schema 107 checkParent( parentDn, schemaManager, SchemaConstants.NORMALIZER ); 108 109 // The new schemaObject's OID must not already exist 110 checkOidIsUniqueForNormalizer( entry ); 111 112 // Build the new Normalizer from the given entry 113 String schemaName = getSchemaName( dn ); 114 115 Normalizer normalizer = factory.getNormalizer( schemaManager, entry, schemaManager.getRegistries(), schemaName ); 116 117 // At this point, the constructed Normalizer has not been checked against the 118 // existing Registries. It will be checked there, if the schema and the 119 // Normalizer are both enabled. 120 Schema schema = schemaManager.getLoadedSchema( schemaName ); 121 List<Throwable> errors = new ArrayList<Throwable>(); 122 123 if ( schema.isEnabled() && normalizer.isEnabled() ) 124 { 125 if ( schemaManager.add( normalizer ) ) 126 { 127 LOG.debug( "Added {} into the enabled schema {}", dn.getName(), schemaName ); 128 } 129 else 130 { 131 String msg = I18n.err( I18n.ERR_364, entry.getDn().getName(), 132 StringTools.listToString( errors ) ); 133 LOG.info( msg ); 134 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg ); 135 } 136 } 137 else 138 { 139 // At least, we associates the Normalizer with the schema 140 schemaManager.getRegistries().associateWithSchema( errors, normalizer ); 141 142 if ( !errors.isEmpty() ) 143 { 144 String msg = I18n.err( I18n.ERR_365, entry.getDn().getName(), 145 StringTools.listToString( errors ) ); 146 147 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg ); 148 } 149 150 LOG.debug( "The normalizer {} cannot be added in schema {}", dn.getName(), schemaName ); 151 } 152 } 153 154 155 /** 156 * {@inheritDoc} 157 */ 158 public void delete( ServerEntry entry, boolean cascade ) throws Exception 159 { 160 DN dn = entry.getDn(); 161 DN parentDn = ( DN ) dn.clone(); 162 parentDn.remove( parentDn.size() - 1 ); 163 164 // The parent DN must be ou=normalizers,cn=<schemaName>,ou=schema 165 checkParent( parentDn, schemaManager, SchemaConstants.NORMALIZER ); 166 167 // Get the Normalizer from the given entry ( it has been grabbed from the server earlier) 168 String schemaName = getSchemaName( entry.getDn() ); 169 Normalizer normalizer = factory.getNormalizer( schemaManager, entry, schemaManager.getRegistries(), schemaName ); 170 171 String oid = normalizer.getOid(); 172 173 if ( isSchemaEnabled( schemaName ) ) 174 { 175 if ( schemaManager.getRegistries().isReferenced( normalizer ) ) 176 { 177 String msg = I18n.err( I18n.ERR_366, entry.getDn().getName(), getReferenced( normalizer ) ); 178 LOG.warn( msg ); 179 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg ); 180 } 181 182 // As the normalizer has the same OID than its attached MR, it won't 183 // be loaded into the schemaManager if it's disabled 184 deleteFromSchema( normalizer, schemaName ); 185 } 186 187 if ( schemaManager.getNormalizerRegistry().contains( oid ) ) 188 { 189 schemaManager.unregisterNormalizer( oid ); 190 LOG.debug( "Removed {} from the enabled schema {}", normalizer, schemaName ); 191 } 192 else 193 { 194 LOG.debug( "Removed {} from the enabled schema {}", normalizer, schemaName ); 195 } 196 } 197 198 199 /** 200 * {@inheritDoc} 201 */ 202 public void rename( ServerEntry entry, RDN newRdn, boolean cascade ) throws Exception 203 { 204 String oldOid = getOid( entry ); 205 String schemaName = getSchemaName( entry.getDn() ); 206 207 if ( schemaManager.getMatchingRuleRegistry().contains( oldOid ) ) 208 { 209 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, 210 I18n.err( I18n.ERR_367, oldOid ) ); 211 } 212 213 String newOid = ( String ) newRdn.getNormValue(); 214 checkOidIsUniqueForNormalizer( newOid ); 215 216 if ( isSchemaEnabled( schemaName ) ) 217 { 218 // Inject the new OID 219 ServerEntry targetEntry = ( ServerEntry ) entry.clone(); 220 targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid ); 221 222 // Inject the new DN 223 DN newDn = new DN( targetEntry.getDn() ); 224 newDn.remove( newDn.size() - 1 ); 225 newDn.add( newRdn ); 226 targetEntry.setDn( newDn ); 227 228 Normalizer normalizer = factory.getNormalizer( schemaManager, targetEntry, schemaManager.getRegistries(), 229 schemaName ); 230 schemaManager.unregisterNormalizer( oldOid ); 231 schemaManager.add( normalizer ); 232 } 233 } 234 235 236 public void moveAndRename( DN oriChildName, DN newParentName, RDN newRdn, boolean deleteOldRn, 237 ServerEntry entry, boolean cascade ) throws Exception 238 { 239 checkNewParent( newParentName ); 240 String oldOid = getOid( entry ); 241 String oldSchemaName = getSchemaName( oriChildName ); 242 String newSchemaName = getSchemaName( newParentName ); 243 244 if ( schemaManager.getMatchingRuleRegistry().contains( oldOid ) ) 245 { 246 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, 247 I18n.err( I18n.ERR_367, oldOid ) ); 248 } 249 250 String oid = ( String ) newRdn.getNormValue(); 251 checkOidIsUniqueForNormalizer( oid ); 252 Normalizer normalizer = factory.getNormalizer( schemaManager, entry, schemaManager.getRegistries(), 253 newSchemaName ); 254 255 if ( isSchemaEnabled( oldSchemaName ) ) 256 { 257 schemaManager.unregisterNormalizer( oldOid ); 258 } 259 260 if ( isSchemaEnabled( newSchemaName ) ) 261 { 262 schemaManager.add( normalizer ); 263 } 264 } 265 266 267 public void move( DN oriChildName, DN newParentName, ServerEntry entry, boolean cascade ) throws Exception 268 { 269 checkNewParent( newParentName ); 270 String oid = getOid( entry ); 271 String oldSchemaName = getSchemaName( oriChildName ); 272 String newSchemaName = getSchemaName( newParentName ); 273 274 if ( schemaManager.getMatchingRuleRegistry().contains( oid ) ) 275 { 276 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, 277 I18n.err( I18n.ERR_368, oid ) ); 278 } 279 280 Normalizer normalizer = factory.getNormalizer( schemaManager, entry, schemaManager.getRegistries(), 281 newSchemaName ); 282 283 if ( isSchemaEnabled( oldSchemaName ) ) 284 { 285 schemaManager.unregisterNormalizer( oid ); 286 } 287 288 if ( isSchemaEnabled( newSchemaName ) ) 289 { 290 schemaManager.add( normalizer ); 291 } 292 } 293 294 295 private void checkOidIsUniqueForNormalizer( String oid ) throws Exception 296 { 297 if ( schemaManager.getNormalizerRegistry().contains( oid ) ) 298 { 299 throw new LdapSchemaViolationException( ResultCodeEnum.OTHER, 300 I18n.err( I18n.ERR_369, oid ) ); 301 } 302 } 303 304 305 private void checkOidIsUniqueForNormalizer( ServerEntry entry ) throws Exception 306 { 307 String oid = getOid( entry ); 308 309 if ( schemaManager.getNormalizerRegistry().contains( oid ) ) 310 { 311 throw new LdapSchemaViolationException( ResultCodeEnum.OTHER, 312 I18n.err( I18n.ERR_369, oid ) ); 313 } 314 } 315 316 317 private void checkNewParent( DN newParent ) throws LdapException 318 { 319 if ( newParent.size() != 3 ) 320 { 321 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION, I18n.err( I18n.ERR_370 ) ); 322 } 323 324 RDN rdn = newParent.getRdn(); 325 326 if ( !schemaManager.getAttributeTypeRegistry().getOidByName( rdn.getNormType() ).equals( 327 SchemaConstants.OU_AT_OID ) ) 328 { 329 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION, I18n.err( I18n.ERR_371 ) ); 330 } 331 332 if ( !( ( String ) rdn.getNormValue() ).equalsIgnoreCase( SchemaConstants.NORMALIZERS_AT ) ) 333 { 334 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION, I18n.err( I18n.ERR_372 ) ); 335 } 336 } 337 }