| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| */ |
| |
| package org.apache.directory.server.core.trigger; |
| |
| |
| import java.text.ParseException; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.directory.server.core.api.CoreSession; |
| import org.apache.directory.server.core.api.DirectoryService; |
| import org.apache.directory.server.core.api.InterceptorEnum; |
| import org.apache.directory.server.core.api.entry.ClonedServerEntry; |
| import org.apache.directory.server.core.api.interceptor.BaseInterceptor; |
| import org.apache.directory.server.core.api.interceptor.context.AddOperationContext; |
| import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext; |
| import org.apache.directory.server.core.api.interceptor.context.LookupOperationContext; |
| import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext; |
| import org.apache.directory.server.core.api.interceptor.context.MoveAndRenameOperationContext; |
| import org.apache.directory.server.core.api.interceptor.context.MoveOperationContext; |
| import org.apache.directory.server.core.api.interceptor.context.OperationContext; |
| import org.apache.directory.server.core.api.interceptor.context.RenameOperationContext; |
| import org.apache.directory.server.core.api.sp.StoredProcEngine; |
| import org.apache.directory.server.core.api.sp.StoredProcEngineConfig; |
| import org.apache.directory.server.core.api.sp.StoredProcExecutionManager; |
| import org.apache.directory.server.core.api.sp.java.JavaStoredProcEngineConfig; |
| import org.apache.directory.server.core.api.subtree.SubentryUtils; |
| import org.apache.directory.server.i18n.I18n; |
| import org.apache.directory.shared.ldap.model.constants.SchemaConstants; |
| import org.apache.directory.shared.ldap.model.entry.Attribute; |
| import org.apache.directory.shared.ldap.model.entry.Entry; |
| import org.apache.directory.shared.ldap.model.entry.Value; |
| import org.apache.directory.shared.ldap.model.exception.LdapException; |
| import org.apache.directory.shared.ldap.model.exception.LdapOperationErrorException; |
| import org.apache.directory.shared.ldap.model.exception.LdapOtherException; |
| import org.apache.directory.shared.ldap.model.name.Dn; |
| import org.apache.directory.shared.ldap.model.name.Rdn; |
| import org.apache.directory.shared.ldap.model.schema.NormalizerMappingResolver; |
| import org.apache.directory.shared.ldap.model.schema.normalizers.OidNormalizer; |
| import org.apache.directory.shared.ldap.trigger.ActionTime; |
| import org.apache.directory.shared.ldap.trigger.LdapOperation; |
| import org.apache.directory.shared.ldap.trigger.TriggerSpecification; |
| import org.apache.directory.shared.ldap.trigger.TriggerSpecification.SPSpec; |
| import org.apache.directory.shared.ldap.trigger.TriggerSpecificationParser; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| |
| /** |
| * The Trigger Service based on the Trigger Specification. |
| * |
| * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> |
| */ |
| public class TriggerInterceptor extends BaseInterceptor |
| { |
| /** the logger for this class */ |
| private static final Logger LOG = LoggerFactory.getLogger( TriggerInterceptor.class ); |
| |
| /** the entry trigger attribute string: entryTrigger */ |
| private static final String ENTRY_TRIGGER_ATTR = "entryTriggerSpecification"; |
| |
| /** a triggerSpecCache that responds to add, delete, and modify attempts */ |
| private TriggerSpecCache triggerSpecCache; |
| |
| /** a normalizing Trigger Specification parser */ |
| private TriggerSpecificationParser triggerParser; |
| |
| /** whether or not this interceptor is activated */ |
| private boolean enabled = true; |
| |
| /** a Trigger Execution Authorizer */ |
| private TriggerExecutionAuthorizer triggerExecutionAuthorizer = new SimpleTriggerExecutionAuthorizer(); |
| |
| private StoredProcExecutionManager manager; |
| |
| /** The SubentryUtils instance */ |
| private static SubentryUtils subentryUtils; |
| |
| |
| /** |
| * Creates a new instance of a TriggerInterceptor. |
| */ |
| public TriggerInterceptor() |
| { |
| super( InterceptorEnum.TRIGGER_INTERCEPTOR ); |
| } |
| |
| |
| /** |
| * Adds prescriptiveTrigger TriggerSpecificaitons to a collection of |
| * TriggerSpeficaitions by accessing the triggerSpecCache. The trigger |
| * specification cache is accessed for each trigger subentry associated |
| * with the entry. |
| * Note that subentries are handled differently: their parent, the administrative |
| * entry is accessed to determine the perscriptiveTriggers effecting the AP |
| * and hence the subentry which is considered to be in the same context. |
| * |
| * @param triggerSpecs the collection of trigger specifications to add to |
| * @param dn the normalized distinguished name of the entry |
| * @param entry the target entry that is considered as the trigger source |
| * @throws Exception if there are problems accessing attribute values |
| * @param proxy the partition nexus proxy |
| */ |
| private void addPrescriptiveTriggerSpecs( OperationContext opContext, List<TriggerSpecification> triggerSpecs, |
| Dn dn, Entry entry ) throws LdapException |
| { |
| |
| /* |
| * If the protected entry is a subentry, then the entry being evaluated |
| * for perscriptiveTriggerss is in fact the administrative entry. By |
| * substituting the administrative entry for the actual subentry the |
| * code below this "if" statement correctly evaluates the effects of |
| * perscriptiveTrigger on the subentry. Basically subentries are considered |
| * to be in the same naming context as their access point so the subentries |
| * effecting their parent entry applies to them as well. |
| */ |
| if ( entry.contains( OBJECT_CLASS_AT, SchemaConstants.SUBENTRY_OC ) ) |
| { |
| Dn parentDn = dn.getParent(); |
| |
| CoreSession session = opContext.getSession(); |
| LookupOperationContext lookupContext = new LookupOperationContext( session, parentDn ); |
| lookupContext.setAttrsId( SchemaConstants.ALL_ATTRIBUTES_ARRAY ); |
| |
| entry = directoryService.getPartitionNexus().lookup( lookupContext ); |
| } |
| |
| Attribute subentries = entry.get( SchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT ); |
| |
| if ( subentries == null ) |
| { |
| return; |
| } |
| |
| for ( Value<?> value : subentries ) |
| { |
| String subentryDn = value.getString(); |
| triggerSpecs.addAll( triggerSpecCache.getSubentryTriggerSpecs( subentryDn ) ); |
| } |
| } |
| |
| |
| /** |
| * Adds the set of entryTriggers to a collection of trigger specifications. |
| * The entryTrigger is parsed and tuples are generated on they fly then |
| * added to the collection. |
| * |
| * @param triggerSpecs the collection of trigger specifications to add to |
| * @param entry the target entry that is considered as the trigger source |
| * @throws Exception if there are problems accessing attribute values |
| */ |
| private void addEntryTriggerSpecs( List<TriggerSpecification> triggerSpecs, Entry entry ) throws LdapException |
| { |
| Attribute entryTrigger = entry.get( ENTRY_TRIGGER_ATTR ); |
| |
| if ( entryTrigger == null ) |
| { |
| return; |
| } |
| |
| for ( Value<?> value : entryTrigger ) |
| { |
| String triggerString = value.getString(); |
| TriggerSpecification item; |
| |
| try |
| { |
| item = triggerParser.parse( triggerString ); |
| } |
| catch ( ParseException e ) |
| { |
| String msg = I18n.err( I18n.ERR_72, triggerString ); |
| LOG.error( msg, e ); |
| throw new LdapOperationErrorException( msg ); |
| } |
| |
| triggerSpecs.add( item ); |
| } |
| } |
| |
| |
| /** |
| * Return a selection of trigger specifications for a certain type of trigger action time. |
| * |
| * @note This method serves as an extion point for new Action Time types. |
| * |
| * @param triggerSpecs the trigger specifications |
| * @param ldapOperation the ldap operation being performed |
| * @return the set of trigger specs for a trigger action |
| */ |
| public Map<ActionTime, List<TriggerSpecification>> getActionTimeMappedTriggerSpecsForOperation( |
| List<TriggerSpecification> triggerSpecs, LdapOperation ldapOperation ) |
| { |
| List<TriggerSpecification> afterTriggerSpecs = new ArrayList<TriggerSpecification>(); |
| Map<ActionTime, List<TriggerSpecification>> triggerSpecMap = new HashMap<ActionTime, List<TriggerSpecification>>(); |
| |
| for ( TriggerSpecification triggerSpec : triggerSpecs ) |
| { |
| if ( triggerSpec.getLdapOperation().equals( ldapOperation ) ) |
| { |
| if ( triggerSpec.getActionTime().equals( ActionTime.AFTER ) ) |
| { |
| afterTriggerSpecs.add( triggerSpec ); |
| } |
| else |
| { |
| |
| } |
| } |
| } |
| |
| triggerSpecMap.put( ActionTime.AFTER, afterTriggerSpecs ); |
| |
| return triggerSpecMap; |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////////// |
| // Interceptor Overrides |
| //////////////////////////////////////////////////////////////////////////// |
| |
| public void init( DirectoryService directoryService ) throws LdapException |
| { |
| super.init( directoryService ); |
| |
| triggerSpecCache = new TriggerSpecCache( directoryService ); |
| |
| triggerParser = new TriggerSpecificationParser( new NormalizerMappingResolver() |
| { |
| public Map<String, OidNormalizer> getNormalizerMapping() throws Exception |
| { |
| return schemaManager.getNormalizerMapping(); |
| } |
| } ); |
| |
| //StoredProcEngineConfig javaxScriptSPEngineConfig = new JavaxStoredProcEngineConfig(); |
| StoredProcEngineConfig javaSPEngineConfig = new JavaStoredProcEngineConfig(); |
| List<StoredProcEngineConfig> spEngineConfigs = new ArrayList<StoredProcEngineConfig>(); |
| //spEngineConfigs.add( javaxScriptSPEngineConfig ); |
| spEngineConfigs.add( javaSPEngineConfig ); |
| String spContainer = "ou=Stored Procedures,ou=system"; |
| manager = new StoredProcExecutionManager( spContainer, spEngineConfigs ); |
| |
| this.enabled = true; // TODO: Get this from the configuration if needed. |
| |
| // Init the SubentryUtils instance |
| subentryUtils = new SubentryUtils( directoryService ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void add( AddOperationContext addContext ) throws LdapException |
| { |
| Dn name = addContext.getDn(); |
| Entry entry = addContext.getEntry(); |
| |
| // Bypass trigger handling if the service is disabled. |
| if ( !enabled ) |
| { |
| next( addContext ); |
| return; |
| } |
| |
| // Gather supplementary data. |
| StoredProcedureParameterInjector injector = new AddStoredProcedureParameterInjector( addContext, name, entry ); |
| |
| // Gather Trigger Specifications which apply to the entry being added. |
| List<TriggerSpecification> triggerSpecs = new ArrayList<TriggerSpecification>(); |
| addPrescriptiveTriggerSpecs( addContext, triggerSpecs, name, entry ); |
| |
| /** |
| * NOTE: We do not handle entryTriggerSpecs for ADD operation. |
| */ |
| |
| Map<ActionTime, List<TriggerSpecification>> triggerMap = getActionTimeMappedTriggerSpecsForOperation( |
| triggerSpecs, LdapOperation.ADD ); |
| |
| next( addContext ); |
| triggerSpecCache.subentryAdded( name, entry ); |
| |
| // Fire AFTER Triggers. |
| List<TriggerSpecification> afterTriggerSpecs = triggerMap.get( ActionTime.AFTER ); |
| executeTriggers( addContext, afterTriggerSpecs, injector ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void delete( DeleteOperationContext deleteContext ) throws LdapException |
| { |
| Dn name = deleteContext.getDn(); |
| |
| // Bypass trigger handling if the service is disabled. |
| if ( !enabled ) |
| { |
| next( deleteContext ); |
| return; |
| } |
| |
| // Gather supplementary data. |
| Entry deletedEntry = deleteContext.getEntry(); |
| |
| StoredProcedureParameterInjector injector = new DeleteStoredProcedureParameterInjector( deleteContext, name ); |
| |
| // Gather Trigger Specifications which apply to the entry being deleted. |
| List<TriggerSpecification> triggerSpecs = new ArrayList<TriggerSpecification>(); |
| addPrescriptiveTriggerSpecs( deleteContext, triggerSpecs, name, deletedEntry ); |
| addEntryTriggerSpecs( triggerSpecs, deletedEntry ); |
| |
| Map<ActionTime, List<TriggerSpecification>> triggerMap = getActionTimeMappedTriggerSpecsForOperation( |
| triggerSpecs, LdapOperation.DELETE ); |
| |
| next( deleteContext ); |
| |
| triggerSpecCache.subentryDeleted( name, deletedEntry ); |
| |
| // Fire AFTER Triggers. |
| List<TriggerSpecification> afterTriggerSpecs = triggerMap.get( ActionTime.AFTER ); |
| executeTriggers( deleteContext, afterTriggerSpecs, injector ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void modify( ModifyOperationContext modifyContext ) throws LdapException |
| { |
| // Bypass trigger handling if the service is disabled. |
| if ( !enabled ) |
| { |
| next( modifyContext ); |
| return; |
| } |
| |
| Dn normName = modifyContext.getDn(); |
| |
| // Gather supplementary data. |
| Entry originalEntry = modifyContext.getEntry(); |
| |
| StoredProcedureParameterInjector injector = new ModifyStoredProcedureParameterInjector( modifyContext ); |
| |
| // Gather Trigger Specifications which apply to the entry being modified. |
| List<TriggerSpecification> triggerSpecs = new ArrayList<TriggerSpecification>(); |
| addPrescriptiveTriggerSpecs( modifyContext, triggerSpecs, normName, originalEntry ); |
| addEntryTriggerSpecs( triggerSpecs, originalEntry ); |
| |
| Map<ActionTime, List<TriggerSpecification>> triggerMap = getActionTimeMappedTriggerSpecsForOperation( |
| triggerSpecs, LdapOperation.MODIFY ); |
| |
| next( modifyContext ); |
| |
| triggerSpecCache.subentryModified( modifyContext, originalEntry ); |
| |
| // Fire AFTER Triggers. |
| List<TriggerSpecification> afterTriggerSpecs = triggerMap.get( ActionTime.AFTER ); |
| executeTriggers( modifyContext, afterTriggerSpecs, injector ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void move( MoveOperationContext moveContext ) throws LdapException |
| { |
| // Bypass trigger handling if the service is disabled. |
| if ( !enabled ) |
| { |
| next( moveContext ); |
| return; |
| } |
| |
| Rdn rdn = moveContext.getRdn(); |
| Dn dn = moveContext.getDn(); |
| Dn newDn = moveContext.getNewDn(); |
| Dn oldSuperior = moveContext.getOldSuperior(); |
| Dn newSuperior = moveContext.getNewSuperior(); |
| |
| // Gather supplementary data. |
| Entry movedEntry = moveContext.getOriginalEntry(); |
| |
| //Rdn newRDN = dn.getRdn(); |
| |
| StoredProcedureParameterInjector injector = new ModifyDNStoredProcedureParameterInjector( moveContext, false, |
| rdn, rdn, oldSuperior, newSuperior, dn, newDn ); |
| |
| // Gather Trigger Specifications which apply to the entry being exported. |
| List<TriggerSpecification> exportTriggerSpecs = new ArrayList<TriggerSpecification>(); |
| addPrescriptiveTriggerSpecs( moveContext, exportTriggerSpecs, dn, movedEntry ); |
| addEntryTriggerSpecs( exportTriggerSpecs, movedEntry ); |
| |
| // Get the entry again without operational attributes |
| // because access control subentry operational attributes |
| // will not be valid at the new location. |
| // This will certainly be fixed by the SubentryInterceptor, |
| // but after this service. |
| CoreSession session = moveContext.getSession(); |
| LookupOperationContext lookupContext = new LookupOperationContext( session, dn, |
| SchemaConstants.ALL_USER_ATTRIBUTES_ARRAY ); |
| |
| Entry importedEntry = directoryService.getPartitionNexus().lookup( lookupContext ); |
| |
| // As the target entry does not exist yet and so |
| // its subentry operational attributes are not there, |
| // we need to construct an entry to represent it |
| // at least with minimal requirements which are object class |
| // and access control subentry operational attributes. |
| Entry fakeImportedEntry = subentryUtils.getSubentryAttributes( newDn, importedEntry ); |
| |
| for ( Attribute attribute : importedEntry ) |
| { |
| fakeImportedEntry.put( attribute ); |
| } |
| |
| // Gather Trigger Specifications which apply to the entry being imported. |
| // Note: Entry Trigger Specifications are not valid for Import. |
| List<TriggerSpecification> importTriggerSpecs = new ArrayList<TriggerSpecification>(); |
| addPrescriptiveTriggerSpecs( moveContext, importTriggerSpecs, newDn, fakeImportedEntry ); |
| |
| Map<ActionTime, List<TriggerSpecification>> exportTriggerMap = getActionTimeMappedTriggerSpecsForOperation( |
| exportTriggerSpecs, LdapOperation.MODIFYDN_EXPORT ); |
| |
| Map<ActionTime, List<TriggerSpecification>> importTriggerMap = getActionTimeMappedTriggerSpecsForOperation( |
| importTriggerSpecs, LdapOperation.MODIFYDN_IMPORT ); |
| |
| next( moveContext ); |
| triggerSpecCache.subentryRenamed( dn, newDn ); |
| |
| // Fire AFTER Triggers. |
| List<TriggerSpecification> afterExportTriggerSpecs = exportTriggerMap.get( ActionTime.AFTER ); |
| List<TriggerSpecification> afterImportTriggerSpecs = importTriggerMap.get( ActionTime.AFTER ); |
| executeTriggers( moveContext, afterExportTriggerSpecs, injector ); |
| executeTriggers( moveContext, afterImportTriggerSpecs, injector ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void moveAndRename( MoveAndRenameOperationContext moveAndRenameContext ) throws LdapException |
| { |
| Dn oldDn = moveAndRenameContext.getDn(); |
| Dn newSuperiorDn = moveAndRenameContext.getNewSuperiorDn(); |
| Rdn newRdn = moveAndRenameContext.getNewRdn(); |
| boolean deleteOldRn = moveAndRenameContext.getDeleteOldRdn(); |
| |
| // Bypass trigger handling if the service is disabled. |
| if ( !enabled ) |
| { |
| next( moveAndRenameContext ); |
| return; |
| } |
| |
| // Gather supplementary data. |
| Entry movedEntry = moveAndRenameContext.getOriginalEntry(); |
| |
| Rdn oldRdn = oldDn.getRdn(); |
| Dn oldSuperiorDn = oldDn.getParent(); |
| Dn oldDN = oldDn; |
| Dn newDn = moveAndRenameContext.getNewDn(); |
| |
| StoredProcedureParameterInjector injector = new ModifyDNStoredProcedureParameterInjector( moveAndRenameContext, |
| deleteOldRn, oldRdn, newRdn, oldSuperiorDn, newSuperiorDn, oldDN, newDn ); |
| |
| // Gather Trigger Specifications which apply to the entry being exported. |
| List<TriggerSpecification> exportTriggerSpecs = new ArrayList<TriggerSpecification>(); |
| addPrescriptiveTriggerSpecs( moveAndRenameContext, exportTriggerSpecs, oldDn, movedEntry ); |
| addEntryTriggerSpecs( exportTriggerSpecs, movedEntry ); |
| |
| // Get the entry again without operational attributes |
| // because access control subentry operational attributes |
| // will not be valid at the new location. |
| // This will certainly be fixed by the SubentryInterceptor, |
| // but after this service. |
| CoreSession session = moveAndRenameContext.getSession(); |
| LookupOperationContext lookupContext = new LookupOperationContext( session, oldDn, |
| SchemaConstants.ALL_USER_ATTRIBUTES_ARRAY ); |
| |
| Entry importedEntry = directoryService.getPartitionNexus().lookup( lookupContext ); |
| |
| // As the target entry does not exist yet and so |
| // its subentry operational attributes are not there, |
| // we need to construct an entry to represent it |
| // at least with minimal requirements which are object class |
| // and access control subentry operational attributes. |
| Entry fakeImportedEntry = subentryUtils.getSubentryAttributes( newDn, importedEntry ); |
| |
| for ( Attribute attribute : importedEntry ) |
| { |
| fakeImportedEntry.put( attribute ); |
| } |
| |
| // Gather Trigger Specifications which apply to the entry being imported. |
| // Note: Entry Trigger Specifications are not valid for Import. |
| List<TriggerSpecification> importTriggerSpecs = new ArrayList<TriggerSpecification>(); |
| addPrescriptiveTriggerSpecs( moveAndRenameContext, importTriggerSpecs, newDn, fakeImportedEntry ); |
| |
| Map<ActionTime, List<TriggerSpecification>> exportTriggerMap = getActionTimeMappedTriggerSpecsForOperation( |
| exportTriggerSpecs, LdapOperation.MODIFYDN_EXPORT ); |
| |
| Map<ActionTime, List<TriggerSpecification>> importTriggerMap = getActionTimeMappedTriggerSpecsForOperation( |
| importTriggerSpecs, LdapOperation.MODIFYDN_IMPORT ); |
| |
| next( moveAndRenameContext ); |
| triggerSpecCache.subentryRenamed( oldDN, newDn ); |
| |
| // Fire AFTER Triggers. |
| List<TriggerSpecification> afterExportTriggerSpecs = exportTriggerMap.get( ActionTime.AFTER ); |
| List<TriggerSpecification> afterImportTriggerSpecs = importTriggerMap.get( ActionTime.AFTER ); |
| executeTriggers( moveAndRenameContext, afterExportTriggerSpecs, injector ); |
| executeTriggers( moveAndRenameContext, afterImportTriggerSpecs, injector ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void rename( RenameOperationContext renameContext ) throws LdapException |
| { |
| Dn name = renameContext.getDn(); |
| Rdn newRdn = renameContext.getNewRdn(); |
| boolean deleteOldRn = renameContext.getDeleteOldRdn(); |
| |
| // Bypass trigger handling if the service is disabled. |
| if ( !enabled ) |
| { |
| next( renameContext ); |
| return; |
| } |
| |
| // Gather supplementary data. |
| Entry renamedEntry = ( ( ClonedServerEntry ) renameContext.getEntry() ).getClonedEntry(); |
| |
| // @TODO : To be completely reviewed !!! |
| Rdn oldRdn = name.getRdn(); |
| Dn oldSuperiorDn = name.getParent(); |
| Dn newSuperiorDn = oldSuperiorDn; |
| Dn oldDn = name; |
| Dn newDn = name; |
| newDn = newDn.add( newRdn ); |
| |
| StoredProcedureParameterInjector injector = new ModifyDNStoredProcedureParameterInjector( renameContext, |
| deleteOldRn, oldRdn, newRdn, oldSuperiorDn, newSuperiorDn, oldDn, newDn ); |
| |
| // Gather Trigger Specifications which apply to the entry being renamed. |
| List<TriggerSpecification> triggerSpecs = new ArrayList<TriggerSpecification>(); |
| addPrescriptiveTriggerSpecs( renameContext, triggerSpecs, name, renamedEntry ); |
| addEntryTriggerSpecs( triggerSpecs, renamedEntry ); |
| |
| Map<ActionTime, List<TriggerSpecification>> triggerMap = getActionTimeMappedTriggerSpecsForOperation( |
| triggerSpecs, LdapOperation.MODIFYDN_RENAME ); |
| |
| next( renameContext ); |
| triggerSpecCache.subentryRenamed( name, newDn ); |
| |
| // Fire AFTER Triggers. |
| List<TriggerSpecification> afterTriggerSpecs = triggerMap.get( ActionTime.AFTER ); |
| executeTriggers( renameContext, afterTriggerSpecs, injector ); |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////////// |
| // Utility Methods |
| //////////////////////////////////////////////////////////////////////////// |
| |
| private Object executeTriggers( OperationContext opContext, List<TriggerSpecification> triggerSpecs, |
| StoredProcedureParameterInjector injector ) throws LdapException |
| { |
| Object result = null; |
| |
| for ( TriggerSpecification triggerSpec : triggerSpecs ) |
| { |
| // TODO: Replace the Authorization Code with a REAL one. |
| if ( triggerExecutionAuthorizer.hasPermission( opContext ) ) |
| { |
| /** |
| * If there is only one Trigger to be executed, this assignment |
| * will make sense (as in INSTEADOF search Triggers). |
| */ |
| result = executeTrigger( opContext, triggerSpec, injector ); |
| } |
| } |
| |
| /** |
| * If only one Trigger has been executed, returning its result |
| * can make sense (as in INSTEADOF Search Triggers). |
| */ |
| return result; |
| } |
| |
| |
| private Object executeTrigger( OperationContext opContext, TriggerSpecification tsec, |
| StoredProcedureParameterInjector injector ) throws LdapException |
| { |
| List<Object> returnValues = new ArrayList<Object>(); |
| List<SPSpec> spSpecs = tsec.getSPSpecs(); |
| |
| for ( SPSpec spSpec : spSpecs ) |
| { |
| List<Object> arguments = new ArrayList<Object>(); |
| arguments.addAll( injector.getArgumentsToInject( opContext, spSpec.getParameters() ) ); |
| Object[] values = arguments.toArray(); |
| Object returnValue = executeProcedure( opContext, spSpec.getName(), values ); |
| returnValues.add( returnValue ); |
| } |
| |
| return returnValues; |
| } |
| |
| |
| private Object executeProcedure( OperationContext opContext, String procedure, Object[] values ) |
| throws LdapException |
| { |
| try |
| { |
| Entry spUnit = manager.findStoredProcUnit( opContext.getSession(), procedure ); |
| StoredProcEngine engine = manager.getStoredProcEngineInstance( spUnit ); |
| |
| return engine.invokeProcedure( opContext.getSession(), procedure, values ); |
| } |
| catch ( Exception e ) |
| { |
| LdapOtherException lne = new LdapOtherException( e.getMessage(), e ); |
| lne.initCause( e ); |
| throw lne; |
| } |
| } |
| } |