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 }