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 */ 020package org.apache.directory.server.core.api.schema.registries.synchronizers; 021 022 023import org.apache.directory.api.ldap.model.constants.MetaSchemaConstants; 024import org.apache.directory.api.ldap.model.constants.SchemaConstants; 025import org.apache.directory.api.ldap.model.entry.Entry; 026import org.apache.directory.api.ldap.model.exception.LdapException; 027import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; 028import org.apache.directory.api.ldap.model.exception.LdapUnwillingToPerformException; 029import org.apache.directory.api.ldap.model.message.ResultCodeEnum; 030import org.apache.directory.api.ldap.model.name.Dn; 031import org.apache.directory.api.ldap.model.name.Rdn; 032import org.apache.directory.api.ldap.model.schema.MatchingRule; 033import org.apache.directory.api.ldap.model.schema.SchemaManager; 034import org.apache.directory.api.ldap.model.schema.registries.Schema; 035import org.apache.directory.api.util.Strings; 036import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext; 037import org.apache.directory.server.i18n.I18n; 038import org.slf4j.Logger; 039import 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 */ 048public class MatchingRuleSynchronizer extends AbstractRegistrySynchronizer 049{ 050 /** A logger for this class */ 051 private static final Logger LOG = LoggerFactory.getLogger( MatchingRuleSynchronizer.class ); 052 053 054 /** 055 * Creates a new instance of MatchingRuleSynchronizer. 056 * 057 * @param schemaManager The global schemaManager 058 * @throws Exception If the initialization failed 059 */ 060 public MatchingRuleSynchronizer( SchemaManager schemaManager ) throws Exception 061 { 062 super( schemaManager ); 063 } 064 065 066 /** 067 * {@inheritDoc} 068 */ 069 @Override 070 public boolean modify( ModifyOperationContext modifyContext, Entry targetEntry, boolean cascade ) 071 throws LdapException 072 { 073 Dn name = modifyContext.getDn(); 074 Entry entry = modifyContext.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 @Override 099 public void add( Entry entry ) throws LdapException 100 { 101 Dn dn = entry.getDn(); 102 Dn parentDn = dn.getParent(); 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 Strings.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 @Override 147 public void delete( Entry entry, boolean cascade ) throws LdapException 148 { 149 Dn dn = entry.getDn(); 150 Dn parentDn = dn.getParent(); 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 Strings.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 @Override 200 public void rename( Entry entry, Rdn newRdn, boolean cascade ) throws LdapException 201 { 202 String schemaName = getSchemaName( entry.getDn() ); 203 MatchingRule oldMr = factory.getMatchingRule( schemaManager, entry, schemaManager.getRegistries(), schemaName ); 204 Entry targetEntry = entry.clone(); 205 String newOid = newRdn.getValue(); 206 checkOidIsUnique( newOid ); 207 208 targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid ); 209 MatchingRule mr = factory.getMatchingRule( schemaManager, targetEntry, schemaManager.getRegistries(), 210 schemaName ); 211 212 if ( isSchemaEnabled( schemaName ) ) 213 { 214 schemaManager.unregisterMatchingRule( oldMr.getOid() ); 215 schemaManager.add( mr ); 216 } 217 else 218 { 219 unregisterOids( oldMr ); 220 registerOids( mr ); 221 } 222 } 223 224 225 /** 226 * {@inheritDoc} 227 */ 228 @Override 229 public void moveAndRename( Dn oriChildName, Dn newParentName, Rdn newRdn, boolean deleteOldRn, 230 Entry entry, boolean cascade ) throws LdapException 231 { 232 checkNewParent( newParentName ); 233 String oldSchemaName = getSchemaName( oriChildName ); 234 String newSchemaName = getSchemaName( newParentName ); 235 MatchingRule oldMr = factory.getMatchingRule( schemaManager, entry, schemaManager.getRegistries(), 236 oldSchemaName ); 237 Entry targetEntry = entry.clone(); 238 String newOid = newRdn.getValue(); 239 checkOidIsUnique( newOid ); 240 241 targetEntry.put( MetaSchemaConstants.M_OID_AT, newOid ); 242 MatchingRule mr = factory.getMatchingRule( schemaManager, targetEntry, schemaManager.getRegistries(), 243 newSchemaName ); 244 245 if ( isSchemaEnabled( oldSchemaName ) ) 246 { 247 schemaManager.unregisterMatchingRule( oldMr.getOid() ); 248 } 249 else 250 { 251 unregisterOids( oldMr ); 252 } 253 254 if ( isSchemaEnabled( newSchemaName ) ) 255 { 256 schemaManager.add( mr ); 257 } 258 else 259 { 260 registerOids( mr ); 261 } 262 } 263 264 265 /** 266 * {@inheritDoc} 267 */ 268 @Override 269 public void move( Dn oriChildName, Dn newParentName, Entry entry, boolean cascade ) throws LdapException 270 { 271 checkNewParent( newParentName ); 272 String oldSchemaName = getSchemaName( oriChildName ); 273 String newSchemaName = getSchemaName( newParentName ); 274 MatchingRule oldMr = factory.getMatchingRule( schemaManager, entry, schemaManager.getRegistries(), 275 oldSchemaName ); 276 MatchingRule newMr = factory.getMatchingRule( schemaManager, entry, schemaManager.getRegistries(), 277 newSchemaName ); 278 279 if ( isSchemaEnabled( oldSchemaName ) ) 280 { 281 schemaManager.unregisterMatchingRule( oldMr.getOid() ); 282 } 283 else 284 { 285 unregisterOids( oldMr ); 286 } 287 288 if ( isSchemaEnabled( newSchemaName ) ) 289 { 290 schemaManager.add( newMr ); 291 } 292 else 293 { 294 registerOids( newMr ); 295 } 296 } 297 298 299 private void checkNewParent( Dn newParent ) throws LdapException 300 { 301 if ( newParent.size() != 3 ) 302 { 303 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION, 304 I18n.err( I18n.ERR_361 ) ); 305 } 306 307 Rdn rdn = newParent.getRdn(); 308 309 if ( !schemaManager.getAttributeTypeRegistry().getOidByName( rdn.getNormType() ).equals( 310 SchemaConstants.OU_AT_OID ) ) 311 { 312 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION, 313 I18n.err( I18n.ERR_362 ) ); 314 } 315 316 if ( !rdn.getValue().equalsIgnoreCase( SchemaConstants.MATCHING_RULES_AT ) ) 317 { 318 throw new LdapInvalidDnException( ResultCodeEnum.NAMING_VIOLATION, 319 I18n.err( I18n.ERR_363 ) ); 320 } 321 } 322}