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.schema; 021 022 023import java.util.Base64; 024 025import org.apache.directory.api.ldap.model.constants.MetaSchemaConstants; 026import org.apache.directory.api.ldap.model.constants.SchemaConstants; 027import org.apache.directory.api.ldap.model.entry.DefaultEntry; 028import org.apache.directory.api.ldap.model.entry.Entry; 029import org.apache.directory.api.ldap.model.exception.LdapException; 030import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; 031import org.apache.directory.api.ldap.model.name.Dn; 032import org.apache.directory.api.ldap.model.schema.AttributeType; 033import org.apache.directory.api.ldap.model.schema.AttributesFactory; 034import org.apache.directory.api.ldap.model.schema.DitContentRule; 035import org.apache.directory.api.ldap.model.schema.DitStructureRule; 036import org.apache.directory.api.ldap.model.schema.LdapSyntax; 037import org.apache.directory.api.ldap.model.schema.MatchingRule; 038import org.apache.directory.api.ldap.model.schema.MatchingRuleUse; 039import org.apache.directory.api.ldap.model.schema.NameForm; 040import org.apache.directory.api.ldap.model.schema.ObjectClass; 041import org.apache.directory.api.ldap.model.schema.SchemaManager; 042import org.apache.directory.api.ldap.model.schema.SchemaObject; 043import org.apache.directory.api.ldap.model.schema.parsers.LdapComparatorDescription; 044import org.apache.directory.api.ldap.model.schema.parsers.NormalizerDescription; 045import org.apache.directory.api.ldap.model.schema.parsers.SyntaxCheckerDescription; 046import org.apache.directory.api.ldap.model.schema.registries.Schema; 047import org.apache.directory.server.core.api.DnFactory; 048import org.apache.directory.server.core.api.interceptor.Interceptor; 049import org.apache.directory.server.core.api.interceptor.context.AddOperationContext; 050import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext; 051import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext; 052import org.apache.directory.server.core.api.partition.Partition; 053 054 055/** 056 * Responsible for translating modify operations on the subschemaSubentry into 057 * operations against entries within the schema partition. 058 * 059 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 060 */ 061public class SchemaSubentryModifier 062{ 063 private AttributesFactory factory = new AttributesFactory(); 064 065 /** The server schemaManager */ 066 private SchemaManager schemaManager; 067 068 /** The Dn factory */ 069 private DnFactory dnFactory; 070 071 072 /** 073 * 074 * Creates a new instance of SchemaSubentryModifier. 075 * 076 * @param schemaManager The server schemaManager 077 * @param dnFactory The Dn factory 078 */ 079 public SchemaSubentryModifier( SchemaManager schemaManager, DnFactory dnFactory ) 080 { 081 this.schemaManager = schemaManager; 082 this.dnFactory = dnFactory; 083 } 084 085 086 private Dn getDn( SchemaObject obj ) throws LdapInvalidDnException 087 { 088 StringBuilder buf = new StringBuilder(); 089 buf.append( "m-oid=" ).append( obj.getOid() ).append( ",ou=" ); 090 091 if ( obj instanceof LdapSyntax ) 092 { 093 buf.append( SchemaConstants.SYNTAXES ); 094 } 095 else if ( obj instanceof MatchingRule ) 096 { 097 buf.append( SchemaConstants.MATCHING_RULES_AT ); 098 } 099 else if ( obj instanceof AttributeType ) 100 { 101 buf.append( SchemaConstants.ATTRIBUTE_TYPES_AT ); 102 } 103 else if ( obj instanceof ObjectClass ) 104 { 105 buf.append( SchemaConstants.OBJECT_CLASSES_AT ); 106 } 107 else if ( obj instanceof MatchingRuleUse ) 108 { 109 buf.append( SchemaConstants.MATCHING_RULE_USE_AT ); 110 } 111 else if ( obj instanceof DitStructureRule ) 112 { 113 buf.append( SchemaConstants.DIT_STRUCTURE_RULES_AT ); 114 } 115 else if ( obj instanceof DitContentRule ) 116 { 117 buf.append( SchemaConstants.DIT_CONTENT_RULES_AT ); 118 } 119 else if ( obj instanceof NameForm ) 120 { 121 buf.append( SchemaConstants.NAME_FORMS_AT ); 122 } 123 124 buf.append( ",cn=" ).append( obj.getSchemaName() ).append( ",ou=schema" ); 125 return dnFactory.create( buf.toString() ); 126 } 127 128 129 public void add( Interceptor nextInterceptor, int position, ModifyOperationContext modifyContext, 130 LdapComparatorDescription comparatorDescription ) throws LdapException 131 { 132 String schemaName = getSchema( comparatorDescription ); 133 Dn dn = dnFactory.create( 134 "m-oid=" + comparatorDescription.getOid(), 135 SchemaConstants.COMPARATORS_PATH, 136 "cn=" + schemaName, 137 SchemaConstants.OU_SCHEMA ); 138 139 Entry entry = getEntry( dn, comparatorDescription ); 140 141 Partition partition = modifyContext.getSession().getDirectoryService().getPartitionNexus().getPartition( dn ); 142 143 AddOperationContext addContext = new AddOperationContext( modifyContext.getSession(), entry ); 144 addContext.setCurrentInterceptor( position ); 145 addContext.setPartition( partition ); 146 addContext.setTransaction( modifyContext.getTransaction() ); 147 148 nextInterceptor.add( addContext ); 149 } 150 151 152 public void add( Interceptor nextInterceptor, int position, ModifyOperationContext modifyContext, 153 NormalizerDescription normalizerDescription ) throws LdapException 154 { 155 String schemaName = getSchema( normalizerDescription ); 156 Dn dn = dnFactory.create( 157 "m-oid=" + normalizerDescription.getOid(), 158 SchemaConstants.NORMALIZERS_PATH, 159 "cn=" + schemaName, 160 SchemaConstants.OU_SCHEMA ); 161 162 Entry entry = getEntry( dn, normalizerDescription ); 163 164 Partition partition = modifyContext.getSession().getDirectoryService().getPartitionNexus().getPartition( dn ); 165 166 AddOperationContext addContext = new AddOperationContext( modifyContext.getSession(), entry ); 167 addContext.setCurrentInterceptor( position ); 168 addContext.setPartition( partition ); 169 addContext.setTransaction( modifyContext.getTransaction() ); 170 171 nextInterceptor.add( addContext ); 172 } 173 174 175 public void add( Interceptor nextInterceptor, int position, ModifyOperationContext modifyContext, 176 SyntaxCheckerDescription syntaxCheckerDescription ) throws LdapException 177 { 178 String schemaName = getSchema( syntaxCheckerDescription ); 179 Dn dn = dnFactory.create( 180 "m-oid=" + syntaxCheckerDescription.getOid(), 181 SchemaConstants.SYNTAX_CHECKERS_PATH, 182 "cn=" + schemaName, 183 SchemaConstants.OU_SCHEMA ); 184 185 Entry entry = getEntry( dn, syntaxCheckerDescription ); 186 187 Partition partition = modifyContext.getSession().getDirectoryService().getPartitionNexus().getPartition( dn ); 188 189 AddOperationContext addContext = new AddOperationContext( modifyContext.getSession(), entry ); 190 addContext.setCurrentInterceptor( position ); 191 addContext.setPartition( partition ); 192 addContext.setTransaction( modifyContext.getTransaction() ); 193 194 nextInterceptor.add( addContext ); 195 } 196 197 198 public void addSchemaObject( Interceptor nextInterceptor, int position, ModifyOperationContext modifyContext, 199 SchemaObject obj ) throws LdapException 200 { 201 Schema schema = schemaManager.getLoadedSchema( obj.getSchemaName() ); 202 Dn dn = getDn( obj ); 203 Entry entry = factory.getAttributes( obj, schema, schemaManager ); 204 entry.setDn( dn ); 205 206 Partition partition = modifyContext.getSession().getDirectoryService().getPartitionNexus().getPartition( dn ); 207 208 AddOperationContext addContext = new AddOperationContext( modifyContext.getSession(), entry ); 209 addContext.setCurrentInterceptor( position ); 210 addContext.setPartition( partition ); 211 addContext.setTransaction( modifyContext.getTransaction() ); 212 213 nextInterceptor.add( addContext ); 214 } 215 216 217 public void deleteSchemaObject( Interceptor nextInterceptor, int position, ModifyOperationContext modifyContext, 218 SchemaObject obj ) throws LdapException 219 { 220 Dn dn = getDn( obj ); 221 222 Partition partition = modifyContext.getSession().getDirectoryService().getPartitionNexus().getPartition( dn ); 223 224 DeleteOperationContext deleteContext = new DeleteOperationContext( modifyContext.getSession(), dn ); 225 deleteContext.setEntry( modifyContext.getSession().lookup( dn ) ); 226 deleteContext.setCurrentInterceptor( position ); 227 deleteContext.setPartition( partition ); 228 deleteContext.setTransaction( modifyContext.getTransaction() ); 229 230 nextInterceptor.delete( deleteContext ); 231 } 232 233 234 public void delete( Interceptor nextInterceptor, int position, ModifyOperationContext modifyContext, 235 NormalizerDescription normalizerDescription ) throws LdapException 236 { 237 String schemaName = getSchema( normalizerDescription ); 238 Dn dn = dnFactory.create( 239 "m-oid=" + normalizerDescription.getOid(), 240 SchemaConstants.NORMALIZERS_PATH, 241 "cn=" + schemaName, 242 SchemaConstants.OU_SCHEMA ); 243 244 Partition partition = modifyContext.getSession().getDirectoryService().getPartitionNexus().getPartition( dn ); 245 246 DeleteOperationContext deleteContext = new DeleteOperationContext( modifyContext.getSession(), dn ); 247 deleteContext.setEntry( modifyContext.getSession().lookup( dn ) ); 248 deleteContext.setCurrentInterceptor( position ); 249 deleteContext.setPartition( partition ); 250 deleteContext.setTransaction( modifyContext.getTransaction() ); 251 252 nextInterceptor.delete( deleteContext ); 253 } 254 255 256 public void delete( Interceptor nextInterceptor, int position, ModifyOperationContext modifyContext, 257 SyntaxCheckerDescription syntaxCheckerDescription ) throws LdapException 258 { 259 String schemaName = getSchema( syntaxCheckerDescription ); 260 Dn dn = dnFactory.create( 261 "m-oid=" + syntaxCheckerDescription.getOid(), 262 SchemaConstants.SYNTAX_CHECKERS_PATH, 263 "cn=" + schemaName, 264 SchemaConstants.OU_SCHEMA ); 265 266 Partition partition = modifyContext.getSession().getDirectoryService().getPartitionNexus().getPartition( dn ); 267 268 DeleteOperationContext deleteContext = new DeleteOperationContext( modifyContext.getSession(), dn ); 269 deleteContext.setEntry( modifyContext.getSession().lookup( dn ) ); 270 deleteContext.setCurrentInterceptor( position ); 271 deleteContext.setPartition( partition ); 272 deleteContext.setTransaction( modifyContext.getTransaction() ); 273 274 nextInterceptor.delete( deleteContext ); 275 } 276 277 278 public void delete( Interceptor nextInterceptor, int position, ModifyOperationContext modifyContext, 279 LdapComparatorDescription comparatorDescription ) throws LdapException 280 { 281 String schemaName = getSchema( comparatorDescription ); 282 Dn dn = dnFactory.create( 283 "m-oid=" + comparatorDescription.getOid(), 284 SchemaConstants.COMPARATORS_PATH, 285 "cn=" + schemaName, 286 SchemaConstants.OU_SCHEMA ); 287 288 Partition partition = modifyContext.getSession().getDirectoryService().getPartitionNexus().getPartition( dn ); 289 290 DeleteOperationContext deleteContext = new DeleteOperationContext( modifyContext.getSession(), dn ); 291 deleteContext.setEntry( modifyContext.getSession().lookup( dn ) ); 292 deleteContext.setCurrentInterceptor( position ); 293 deleteContext.setPartition( partition ); 294 deleteContext.setTransaction( modifyContext.getTransaction() ); 295 296 nextInterceptor.delete( deleteContext ); 297 } 298 299 300 private Entry getEntry( Dn dn, LdapComparatorDescription comparatorDescription ) 301 { 302 Entry entry = new DefaultEntry( schemaManager, dn ); 303 304 entry.put( SchemaConstants.OBJECT_CLASS_AT, 305 SchemaConstants.TOP_OC, 306 MetaSchemaConstants.META_TOP_OC, 307 MetaSchemaConstants.META_COMPARATOR_OC ); 308 309 entry.put( MetaSchemaConstants.M_OID_AT, comparatorDescription.getOid() ); 310 entry.put( MetaSchemaConstants.M_FQCN_AT, comparatorDescription.getFqcn() ); 311 312 if ( comparatorDescription.getBytecode() != null ) 313 { 314 entry.put( MetaSchemaConstants.M_BYTECODE_AT, 315 Base64.getDecoder().decode( comparatorDescription.getBytecode() ) ); 316 } 317 318 if ( comparatorDescription.getDescription() != null ) 319 { 320 entry.put( MetaSchemaConstants.M_DESCRIPTION_AT, comparatorDescription.getDescription() ); 321 } 322 323 return entry; 324 } 325 326 327 private Entry getEntry( Dn dn, NormalizerDescription normalizerDescription ) 328 { 329 Entry entry = new DefaultEntry( schemaManager, dn ); 330 331 entry.put( SchemaConstants.OBJECT_CLASS_AT, 332 SchemaConstants.TOP_OC, 333 MetaSchemaConstants.META_TOP_OC, 334 MetaSchemaConstants.META_NORMALIZER_OC ); 335 336 entry.put( MetaSchemaConstants.M_OID_AT, normalizerDescription.getOid() ); 337 entry.put( MetaSchemaConstants.M_FQCN_AT, normalizerDescription.getFqcn() ); 338 339 if ( normalizerDescription.getBytecode() != null ) 340 { 341 entry.put( MetaSchemaConstants.M_BYTECODE_AT, 342 Base64.getDecoder().decode( normalizerDescription.getBytecode() ) ); 343 } 344 345 if ( normalizerDescription.getDescription() != null ) 346 { 347 entry.put( MetaSchemaConstants.M_DESCRIPTION_AT, normalizerDescription.getDescription() ); 348 } 349 350 return entry; 351 } 352 353 354 private String getSchema( SchemaObject desc ) 355 { 356 if ( desc.getExtensions().containsKey( MetaSchemaConstants.X_SCHEMA_AT ) ) 357 { 358 return desc.getExtensions().get( MetaSchemaConstants.X_SCHEMA_AT ).get( 0 ); 359 } 360 361 return MetaSchemaConstants.SCHEMA_OTHER; 362 } 363 364 365 private Entry getEntry( Dn dn, SyntaxCheckerDescription syntaxCheckerDescription ) 366 { 367 Entry entry = new DefaultEntry( schemaManager, dn ); 368 369 entry.put( SchemaConstants.OBJECT_CLASS_AT, 370 SchemaConstants.TOP_OC, 371 MetaSchemaConstants.META_TOP_OC, 372 MetaSchemaConstants.META_SYNTAX_CHECKER_OC ); 373 374 entry.put( MetaSchemaConstants.M_OID_AT, syntaxCheckerDescription.getOid() ); 375 entry.put( MetaSchemaConstants.M_FQCN_AT, syntaxCheckerDescription.getFqcn() ); 376 377 if ( syntaxCheckerDescription.getBytecode() != null ) 378 { 379 entry.put( MetaSchemaConstants.M_BYTECODE_AT, 380 Base64.getDecoder().decode( syntaxCheckerDescription.getBytecode() ) ); 381 } 382 383 if ( syntaxCheckerDescription.getDescription() != null ) 384 { 385 entry.put( MetaSchemaConstants.M_DESCRIPTION_AT, syntaxCheckerDescription.getDescription() ); 386 } 387 388 return entry; 389 } 390}