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.LdapUnwillingToPerformException; 031 import org.apache.directory.shared.ldap.message.ResultCodeEnum; 032 import org.apache.directory.shared.ldap.name.DN; 033 import org.apache.directory.shared.ldap.name.RDN; 034 import org.apache.directory.shared.ldap.schema.MatchingRule; 035 import org.apache.directory.shared.ldap.schema.SchemaManager; 036 import org.apache.directory.shared.ldap.schema.registries.Schema; 037 import org.apache.directory.shared.ldap.util.StringTools; 038 import org.slf4j.Logger; 039 import org.slf4j.LoggerFactory; 040 041 042 /** 043 * A handler for operations performed to add, delete, modify, rename and 044 * move schema normalizers. 045 * 046 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 047 * @version $Rev$, $Date$ 048 */ 049 public class MatchingRuleSynchronizer extends AbstractRegistrySynchronizer 050 { 051 /** A logger for this class */ 052 private static final Logger LOG = LoggerFactory.getLogger( MatchingRuleSynchronizer.class ); 053 054 055 /** 056 * Creates a new instance of MatchingRuleSynchronizer. 057 * 058 * @param schemaManager The global schemaManager 059 * @throws Exception If the initialization failed 060 */ 061 public MatchingRuleSynchronizer( SchemaManager schemaManager ) throws Exception 062 { 063 super( schemaManager ); 064 } 065 066 067 /** 068 * {@inheritDoc} 069 */ 070 public boolean modify( ModifyOperationContext opContext, ServerEntry targetEntry, boolean cascade ) 071 throws Exception 072 { 073 DN name = opContext.getDn(); 074 ServerEntry entry = opContext.getEntry(); 075 String schemaName = getSchemaName( name ); 076 MatchingRule mr = factory.getMatchingRule( schemaManager, targetEntry, schemaManager.getRegistries(), 077 schemaName ); 078 079 String oldOid = getOid( entry ); 080 081 if ( isSchemaEnabled( schemaName ) ) 082 { 083 schemaManager.unregisterMatchingRule( oldOid ); 084 schemaManager.add( mr ); 085 086 return SCHEMA_MODIFIED; 087 } 088 else 089 { 090 return SCHEMA_UNCHANGED; 091 } 092 } 093 094 095 /** 096 * {@inheritDoc} 097 */ 098 public void add( ServerEntry entry ) throws Exception 099 { 100 DN dn = entry.getDn(); 101 DN parentDn = ( DN ) dn.clone(); 102 parentDn.remove( parentDn.size() - 1 ); 103 104 // The parent DN must be ou=matchingrules,cn=<schemaName>,ou=schema 105 checkParent( parentDn, schemaManager, SchemaConstants.MATCHING_RULE ); 106 107 // The new schemaObject's OID must not already exist 108 checkOidIsUnique( entry ); 109 110 // Build the new MatchingRule from the given entry 111 String schemaName = getSchemaName( dn ); 112 113 MatchingRule matchingRule = factory.getMatchingRule( schemaManager, entry, schemaManager.getRegistries(), 114 schemaName ); 115 116 // At this point, the constructed MatchingRule has not been checked against the 117 // existing Registries. It may be broken (missing SUP, or such), it will be checked 118 // there, if the schema and the MatchingRule are both enabled. 119 Schema schema = schemaManager.getLoadedSchema( schemaName ); 120 121 if ( schema.isEnabled() && matchingRule.isEnabled() ) 122 { 123 if ( schemaManager.add( matchingRule ) ) 124 { 125 LOG.debug( "Added {} into the enabled schema {}", dn.getName(), schemaName ); 126 } 127 else 128 { 129 // We have some error : reject the addition and get out 130 String msg = I18n.err( I18n.ERR_360, 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 MztchingRule {} cannot be added in the disabled schema {}.", matchingRule, 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=matchingrules,cn=<schemaName>,ou=schema 153 checkParent( parentDn, schemaManager, SchemaConstants.MATCHING_RULE ); 154 155 // Get the SchemaName 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 MatchingRule {} cannot be removed from the disabled schema {}.", 165 dn.getName(), schemaName ); 166 167 return; 168 } 169 170 // Test that the Oid exists 171 MatchingRule matchingRule = ( MatchingRule ) checkOidExists( entry ); 172 173 if ( schema.isEnabled() && matchingRule.isEnabled() ) 174 { 175 if ( schemaManager.delete( matchingRule ) ) 176 { 177 LOG.debug( "Removed {} from the schema {}", matchingRule, schemaName ); 178 } 179 else 180 { 181 // We have some error : reject the deletion and get out 182 // The schema is disabled. We still have to update the backend 183 String msg = I18n.err( I18n.ERR_360, entry.getDn().getName(), 184 StringTools.listToString( schemaManager.getErrors() ) ); 185 LOG.info( msg ); 186 throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM, msg ); 187 } 188 } 189 else 190 { 191 LOG.debug( "Removed {} from the disabled schema {}", matchingRule, schemaName ); 192 } 193 } 194 195 196 /** 197 * {@inheritDoc} 198 */ 199 public void rename( ServerEntry entry, RDN newRdn, boolean cascade ) throws Exception 200 { 201 String schemaName = getSchemaName( entry.getDn() ); 202 MatchingRule oldMr = factory.getMatchingRule( schemaManager, entry, schemaManager.getRegistries(), schemaName ); 203 ServerEntry targetEntry = ( ServerEntry ) entry.clone(); 204 String newOid = ( String ) newRdn.getNormValue(); 205 checkOidIsUnique( newOid ); 206 207 targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid ); 208 MatchingRule mr = factory.getMatchingRule( schemaManager, targetEntry, schemaManager.getRegistries(), 209 schemaName ); 210 211 if ( isSchemaEnabled( schemaName ) ) 212 { 213 schemaManager.unregisterMatchingRule( oldMr.getOid() ); 214 schemaManager.add( mr ); 215 } 216 else 217 { 218 unregisterOids( oldMr ); 219 registerOids( mr ); 220 } 221 } 222 223 224 public void moveAndRename( DN oriChildName, DN newParentName, RDN newRdn, boolean deleteOldRn, 225 ServerEntry entry, boolean cascade ) throws Exception 226 { 227 checkNewParent( newParentName ); 228 String oldSchemaName = getSchemaName( oriChildName ); 229 String newSchemaName = getSchemaName( newParentName ); 230 MatchingRule oldMr = factory.getMatchingRule( schemaManager, entry, schemaManager.getRegistries(), 231 oldSchemaName ); 232 ServerEntry targetEntry = ( ServerEntry ) entry.clone(); 233 String newOid = ( String ) newRdn.getNormValue(); 234 checkOidIsUnique( newOid ); 235 236 targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid ); 237 MatchingRule mr = factory.getMatchingRule( schemaManager, targetEntry, schemaManager.getRegistries(), 238 newSchemaName ); 239 240 if ( isSchemaEnabled( oldSchemaName ) ) 241 { 242 schemaManager.unregisterMatchingRule( oldMr.getOid() ); 243 } 244 else 245 { 246 unregisterOids( oldMr ); 247 } 248 249 if ( isSchemaEnabled( newSchemaName ) ) 250 { 251 schemaManager.add( mr ); 252 } 253 else 254 { 255 registerOids( mr ); 256 } 257 } 258 259 260 public void move( DN oriChildName, DN newParentName, ServerEntry entry, boolean cascade ) throws Exception 261 { 262 checkNewParent( newParentName ); 263 String oldSchemaName = getSchemaName( oriChildName ); 264 String newSchemaName = getSchemaName( newParentName ); 265 MatchingRule oldMr = factory.getMatchingRule( schemaManager, entry, schemaManager.getRegistries(), 266 oldSchemaName ); 267 MatchingRule newMr = factory.getMatchingRule( schemaManager, entry, schemaManager.getRegistries(), 268 newSchemaName ); 269 270 if ( isSchemaEnabled( oldSchemaName ) ) 271 { 272 schemaManager.unregisterMatchingRule( oldMr.getOid() ); 273 } 274 else 275 { 276 unregisterOids( oldMr ); 277 } 278 279 if ( isSchemaEnabled( newSchemaName ) ) 280 { 281 schemaManager.add( newMr ); 282 } 283 else 284 { 285 registerOids( newMr ); 286 } 287 } 288 289 290 private void checkNewParent( DN newParent ) throws LdapException 291 { 292 if ( newParent.size() != 3 ) 293 { 294 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION, 295 I18n.err( I18n.ERR_361 ) ); 296 } 297 298 RDN rdn = newParent.getRdn(); 299 300 if ( !schemaManager.getAttributeTypeRegistry().getOidByName( rdn.getNormType() ).equals( 301 SchemaConstants.OU_AT_OID ) ) 302 { 303 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION, 304 I18n.err( I18n.ERR_362 ) ); 305 } 306 307 if ( !( ( String ) rdn.getNormValue() ).equalsIgnoreCase( SchemaConstants.MATCHING_RULES_AT ) ) 308 { 309 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION, 310 I18n.err( I18n.ERR_363 ) ); 311 } 312 } 313 }