Scheduled Actions

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2673 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Andrew Hind
2006-04-20 13:57:06 +00:00
parent b2998a79fd
commit 05525aff09
19 changed files with 2769 additions and 1 deletions

View File

@@ -0,0 +1,645 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* 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.alfresco.repo.action.scheduled;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.TransactionUtil;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
/**
* Abstract action support.
*
* Each action applies to a set of nodes.
*
* These actions may be executed in one overall transaction or one individual transaction. If actions are in individual transactions an error may halt subsequent execution or
* processing can try and invoke the action for each node.
*
* @author Andy Hind
*/
public abstract class AbstractScheduledAction implements ScheduledActionDefinition
{
/**
* Logging
*/
private static Log s_logger = LogFactory.getLog(AbstractScheduledAction.class);
/**
* Enum to define the transaction mode.
*
* @author Andy Hind
*/
public enum TransactionMode
{
ISOLATED_TRANSACTIONS, UNTIL_FIRST_FAILURE, ONE_TRANSACTION;
public static TransactionMode getTransactionMode(String transactionModeString)
{
TransactionMode transactionMode;
if (transactionModeString.equalsIgnoreCase("ISOLATED_TRANSACTIONS"))
{
transactionMode = TransactionMode.ISOLATED_TRANSACTIONS;
}
else if (transactionModeString.equalsIgnoreCase("UNTIL_FIRST_FAILURE"))
{
transactionMode = TransactionMode.UNTIL_FIRST_FAILURE;
}
else if (transactionModeString.equalsIgnoreCase("ONE_TRANSACTION"))
{
transactionMode = TransactionMode.ONE_TRANSACTION;
}
else
{
// The default ....
transactionMode = TransactionMode.ISOLATED_TRANSACTIONS;
}
return transactionMode;
}
}
/**
* Enum to define if compensating actions are run.
*
* @author Andy Hind
*/
public enum CompensatingActionMode
{
RUN_COMPENSATING_ACTIONS_ON_FAILURE, IGNORE;
public static CompensatingActionMode getCompensatingActionMode(String compensatingActionModeString)
{
CompensatingActionMode compensatingActionMode;
if (compensatingActionModeString.equalsIgnoreCase("RUN_COMPENSATING_ACTIONS_ON_FAILURE"))
{
compensatingActionMode = CompensatingActionMode.RUN_COMPENSATING_ACTIONS_ON_FAILURE;
}
else if (compensatingActionModeString.equalsIgnoreCase("IGNORE"))
{
compensatingActionMode = CompensatingActionMode.IGNORE;
}
else
{
// The default ....
compensatingActionMode = CompensatingActionMode.IGNORE;
}
return compensatingActionMode;
}
}
/*
* Key used to pass the action in the quartz job definition
*/
private static final String ACTION_JOB_DATA_MAP_KEY = "Action";
/*
* The Action service.
*/
private ActionService actionService;
/*
* The user in whose name the action will run.
*/
private String runAsUser;
/*
* The template definition of the action.
*/
private TemplateActionDefinition templateActionDefinition;
/*
* The transaction mode in which all the nodes found by this sceduled action will be treated.
*/
private TransactionMode transactionMode = TransactionMode.ISOLATED_TRANSACTIONS;
/*
* Control if compensating actions will be used. The default is not to apply compensating actions.
*/
private CompensatingActionMode compensatingActionMode = CompensatingActionMode.IGNORE;
/*
* The transaction service
*/
private TransactionService transactionService;
/**
* Simple constructor
*/
public AbstractScheduledAction()
{
super();
}
/**
* Get the user in whose name to run the action.
*
* @return
*/
public String getRunAsUser()
{
return runAsUser;
}
/**
* Set the user in whose name to run the action.
*
* @param runAsUser
*/
public void setRunAsUser(String runAsUser)
{
this.runAsUser = runAsUser;
}
/**
* Get the template definition.
*/
public TemplateActionDefinition getTemplateActionDefinition()
{
return templateActionDefinition;
}
/**
* Set the action service - IOC.
*
* @param actionService
*/
public void setActionService(ActionService actionService)
{
this.actionService = actionService;
}
/**
* Get the actions service.
*
* @return
*/
public ActionService getActionService()
{
return actionService;
}
/**
* Set the behaviour for compensating actiions.
*
* @param compensatingActionModeString
*/
public void setCompensatingActionMode(String compensatingActionModeString)
{
this.compensatingActionMode = CompensatingActionMode.getCompensatingActionMode(compensatingActionModeString);
}
/**
* Set transactional behaviour.
*
* @param transactionModeString
*/
public void setTransactionMode(String transactionModeString)
{
this.transactionMode = TransactionMode.getTransactionMode(transactionModeString);
}
/**
* Get the transaction service.
*
* @return
*/
public TransactionService getTransactionService()
{
return transactionService;
}
/**
* Set the transactions service - IOC.
*
* @param transactionService
*/
public void setTransactionService(TransactionService transactionService)
{
this.transactionService = transactionService;
}
/**
* Set the template action that is used to generate the real action for each node.
*/
public void setTemplateActionDefinition(TemplateActionDefinition templateActionDefinition)
{
this.templateActionDefinition = templateActionDefinition;
}
/**
* Get the behaviour for compensating actions.
*
* @return
*/
public CompensatingActionMode getCompensatingActionModeEnum()
{
return compensatingActionMode;
}
/**
* Get the transaction mode.
*
* @return
*/
public TransactionMode getTransactionModeEnum()
{
return transactionMode;
}
public void register(Scheduler scheduler) throws SchedulerException
{
JobDetail jobDetail = getJobDetail();
Trigger trigger = getTrigger();
if (s_logger.isDebugEnabled())
{
s_logger.debug(("Registering job: " + jobDetail));
s_logger.debug(("With trigger: " + trigger));
}
scheduler.scheduleJob(jobDetail, trigger);
}
/**
* Get the trigger definition for this job. Used to register with the injected scheduler.
*
* @return
*/
public abstract Trigger getTrigger();
/**
* Get the list of nodes against which this action should run.
*
* @return
*/
public abstract List<NodeRef> getNodes();
/**
* Generate the actual action for the given node from the action template.
*
* @param nodeRef
* @return
*/
public abstract Action getAction(NodeRef nodeRef);
/**
* Get the job detail.
*
* @return
*/
private JobDetail getJobDetail()
{
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put(ACTION_JOB_DATA_MAP_KEY, this);
JobDetail jobDetail = new JobDetail();
jobDetail.setName(getJobName());
jobDetail.setGroup(getJobGroup());
jobDetail.setJobDataMap(jobDataMap);
jobDetail.setJobClass(JobDefinition.class);
return jobDetail;
}
/**
* Job definition to run scheduled action
*
* @author Andy Hind
*/
public static class JobDefinition implements Job
{
public void execute(JobExecutionContext ctx) throws JobExecutionException
{
final AbstractScheduledAction abstractScheduledAction = (AbstractScheduledAction) ctx.getJobDetail()
.getJobDataMap().get(ACTION_JOB_DATA_MAP_KEY);
// Run as the required user
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>()
{
public Object doWork()
{
// Get the list of nodes
List<NodeRef> nodes = abstractScheduledAction.getNodes();
if (s_logger.isDebugEnabled())
{
s_logger.debug("Found " + nodes.size());
}
// Individual transactions
if (abstractScheduledAction.getTransactionModeEnum() == TransactionMode.ONE_TRANSACTION)
{
if (s_logger.isDebugEnabled())
{
s_logger.debug("Executing in one transaction");
}
runTransactionalActions(nodes);
return null;
}
// Single global transaction
else
{
if (s_logger.isDebugEnabled())
{
s_logger.debug("Executing in individual transaction");
}
for (NodeRef nodeRef : nodes)
{
try
{
runTransactionalAction(nodeRef);
}
catch (Throwable t)
{
if (abstractScheduledAction.getTransactionModeEnum() == TransactionMode.ISOLATED_TRANSACTIONS)
{
s_logger
.error(
"Error in scheduled action executed in isolated transactions (other actions will continue",
t);
}
else
{
throwRuntimeException(t);
}
}
}
return null;
}
}
/**
* Apply the action to all nodes in one overall transaction
*
* @param nodes
*/
public void runTransactionalActions(final List<NodeRef> nodes)
{
boolean runCompensatingActions = abstractScheduledAction.getCompensatingActionModeEnum() == CompensatingActionMode.RUN_COMPENSATING_ACTIONS_ON_FAILURE;
try
{
TransactionUtil.executeInUserTransaction(abstractScheduledAction.getTransactionService(),
new TransactionUtil.TransactionWork<Object>()
{
public Object doWork() throws Exception
{
// Build the full list of compensating actions
// If anything goes wrong we need to do all these instead
List<Pair<Action, NodeRef>> compensatingActions = new ArrayList<Pair<Action, NodeRef>>(
nodes.size());
for (NodeRef nodeRef : nodes)
{
Action action = abstractScheduledAction.getAction(nodeRef);
Action compensatingAction = action.getCompensatingAction();
if (compensatingAction != null)
{
compensatingActions.add(new Pair<Action, NodeRef>(compensatingAction,
nodeRef));
}
}
// Run all the actions
try
{
for (NodeRef nodeRef : nodes)
{
Action action = abstractScheduledAction.getAction(nodeRef);
abstractScheduledAction.getActionService().executeAction(action,
nodeRef);
}
return null;
}
catch (Throwable t)
{
// Throw exception to trigger compensating actions
throw new CompensatingActionException("Requires compensating action", t,
compensatingActions);
}
}
});
}
catch (Throwable t)
{
// Do compensation if required
doCompensation(runCompensatingActions, true, t);
}
}
/**
* Run compensating actions.
*
* These are always in their own transaction. We try to run all compensating actions.
*
* @param runCompensatingActions
* @param rethrow
* @param t
*/
private void doCompensation(boolean runCompensatingActions, boolean rethrow, Throwable t)
{
// If the error triggers compensation, and they should be processed.
if (runCompensatingActions && (t instanceof CompensatingActionException))
{
CompensatingActionException cae = (CompensatingActionException) t.getCause();
for (Pair<Action, NodeRef> pair : cae.getCompensatingActions())
if ((pair != null) && (pair.getFirst() != null) && (pair.getSecond() != null))
{
try
{
// try the compensating action in its own tx
runTransactionalCompensatingAction(pair);
}
catch (Throwable cat)
{
s_logger.error("Error executing compensating action", t);
}
}
}
if (rethrow)
{
throwRuntimeException(t);
}
}
/**
* Run a single transaction in its own tx
*
* @param nodeRef
*/
public void runTransactionalAction(final NodeRef nodeRef)
{
boolean runCompensatingActions = abstractScheduledAction.getCompensatingActionModeEnum() == CompensatingActionMode.RUN_COMPENSATING_ACTIONS_ON_FAILURE;
boolean rethrow = abstractScheduledAction.getTransactionModeEnum() != TransactionMode.ISOLATED_TRANSACTIONS;
try
{
TransactionUtil.executeInUserTransaction(abstractScheduledAction.getTransactionService(),
new TransactionUtil.TransactionWork<Object>()
{
public Object doWork() throws Exception
{
// try action - failure triggers compensation
Action action = abstractScheduledAction.getAction(nodeRef);
Action compensatingAction = action.getCompensatingAction();
try
{
abstractScheduledAction.getActionService().executeAction(action, nodeRef);
return null;
}
catch (Throwable t)
{
if (compensatingAction != null)
{
throw new CompensatingActionException(
"Requires compensating action",
t,
Collections
.<Pair<Action, NodeRef>> singletonList(new Pair<Action, NodeRef>(
action.getCompensatingAction(), nodeRef)));
}
else
{
return throwRuntimeException(t);
}
}
}
});
}
catch (Throwable t)
{
// Run compensating action if required
doCompensation(runCompensatingActions, rethrow, t);
}
}
/**
* Manage running a compensating action and chaining all its compensating actions until done
*
* @param pair
*/
public void runTransactionalCompensatingAction(final Pair<Action, NodeRef> pair)
{
boolean runCompensatingActions = abstractScheduledAction.getCompensatingActionModeEnum() == CompensatingActionMode.RUN_COMPENSATING_ACTIONS_ON_FAILURE;
try
{
TransactionUtil.executeInUserTransaction(abstractScheduledAction.getTransactionService(),
new TransactionUtil.TransactionWork<Object>()
{
public Object doWork() throws Exception
{
try
{
abstractScheduledAction.getActionService().executeAction(pair.getFirst(),
pair.getSecond());
return null;
}
catch (Throwable t)
{
List<Pair<Action, NodeRef>> compensatingActions = new ArrayList<Pair<Action, NodeRef>>(
1);
if (pair.getFirst().getCompensatingAction() != null)
{
compensatingActions.add(new Pair<Action, NodeRef>(pair.getFirst()
.getCompensatingAction(), pair.getSecond()));
}
throw new CompensatingActionException("Requires compensating action", t,
compensatingActions);
}
}
});
}
catch (Throwable t)
{
// Run compensation
doCompensation(runCompensatingActions, true, t);
}
}
}, abstractScheduledAction.getRunAsUser());
}
}
/**
* Simple class to hold to related objects
*
* @author Andy Hind
*/
public static class Pair<FIRST, SECOND>
{
FIRST first;
SECOND second;
Pair(FIRST first, SECOND second)
{
this.first = first;
this.second = second;
}
FIRST getFirst()
{
return first;
}
SECOND getSecond()
{
return second;
}
}
/**
* Support method to translate exceptions to runtime exceptions.
*
* @param t
* @return
*/
private static Object throwRuntimeException(Throwable t)
{
if (t instanceof RuntimeException)
{
throw (RuntimeException) t;
}
else
{
throw new RuntimeException("Error during execution of transaction.", t);
}
}
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* 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.alfresco.repo.action.scheduled;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.repository.TemplateService;
/**
* Common attributes for template action definitions.
*
* @author Andy Hind
*/
public abstract class AbstractTemplateActionDefinition implements TemplateActionDefinition
{
/*
* The action service
*/
public ActionService actionService;
/*
* The template service
*/
public TemplateService templateService;
/*
* The compensating action
*/
protected TemplateActionDefinition compensatingTemplateActionDefinition;
/**
* Simple construction
*/
public AbstractTemplateActionDefinition()
{
super();
}
/**
* Get the action service.
*
* @return
*/
public ActionService getActionService()
{
return actionService;
}
/**
* Set the action service - IOC.
*
* @param actionService
*/
public void setActionService(ActionService actionService)
{
this.actionService = actionService;
}
/**
* Get the template service.
*
* @return
*/
public TemplateService getTemplateService()
{
return templateService;
}
/**
* Set the template service - IOC.
*
* @param templateService
*/
public void setTemplateService(TemplateService templateService)
{
this.templateService = templateService;
}
/**
* Set the template to define the compensating action.
*
* @param compensatingTemplateActionDefinition
*/
public void setCompensatingTemplateCompositeActionDefinition(
TemplateActionDefinition compensatingTemplateActionDefinition)
{
this.compensatingTemplateActionDefinition = compensatingTemplateActionDefinition;
}
/**
* Get the template that defines the conpensating action.
*
* @return
*/
public TemplateActionDefinition getCompensatingTemplateCompositeActionDefinition()
{
return compensatingTemplateActionDefinition;
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* 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.alfresco.repo.action.scheduled;
import java.util.List;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.action.scheduled.AbstractScheduledAction.Pair;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Error that triggers the execution of compensating actions.
*
* The required compensating actions are contained by the exception thrown.
*
* @author Andy Hind
*/
public class CompensatingActionException extends AlfrescoRuntimeException
{
/**
* Comment for <code>serialVersionUID</code>
*/
private static final long serialVersionUID = 2144573075007116603L;
List<Pair<Action, NodeRef>> compensatingActions;
public CompensatingActionException(String msgId)
{
super(msgId);
}
public CompensatingActionException(String msgId, Throwable cause, List<Pair<Action, NodeRef>> compensatingActions)
{
super(msgId, cause);
this.compensatingActions = compensatingActions;
}
public List<Pair<Action, NodeRef>> getCompensatingActions()
{
return compensatingActions;
}
public CompensatingActionException(String msgId, Object[] msgParams)
{
super(msgId, msgParams);
}
public CompensatingActionException(String msgId, Throwable cause)
{
super(msgId, cause);
}
public CompensatingActionException(String msgId, Object[] msgParams, Throwable cause)
{
super(msgId, msgParams, cause);
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* 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.alfresco.repo.action.scheduled;
import java.util.List;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.CompositeAction;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* The template to define a composite action.
*
* @author Andy Hind
*/
public class CompositeTemplateActionDefinition extends AbstractTemplateActionDefinition
{
/*
* The list of action templates that define this composite
*/
private List<TemplateActionDefinition> templateActionDefinitions;
public CompositeTemplateActionDefinition()
{
super();
}
/**
* Set the action templates - IOC.
*
* @param templateActionDefinitions
*/
public void setTemplateActionDefinitions(List<TemplateActionDefinition> templateActionDefinitions)
{
this.templateActionDefinitions = templateActionDefinitions;
}
/**
* Get the list of template actions.
*
* @return
*/
public List<TemplateActionDefinition> templateActionDefinitions()
{
return templateActionDefinitions;
}
/**
* Build the composite action in the context of the given node.
*
*/
public Action getAction(NodeRef nodeRef)
{
CompositeAction compositeAction = getActionService().createCompositeAction();
for(TemplateActionDefinition tad : templateActionDefinitions)
{
compositeAction.addAction(tad.getAction(nodeRef));
}
if (getCompensatingTemplateCompositeActionDefinition() != null)
{
compositeAction.setCompensatingAction(getCompensatingTemplateCompositeActionDefinition().getAction(nodeRef));
}
return compositeAction;
}
}

View File

@@ -0,0 +1,309 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* 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.alfresco.repo.action.scheduled;
import java.text.ParseException;
import java.util.LinkedList;
import java.util.List;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.TemplateService;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.ResultSetRow;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
import org.quartz.CronTrigger;
import org.quartz.Scheduler;
import org.quartz.Trigger;
/**
* A scheduled action for which the trigger is defined in the standard cron format and the nodes to which the
* action should be run is defined from the nodes selected by query.
*
* @author Andy Hind
*/
public class CronScheduledQueryBasedTemplateActionDefinition extends AbstractScheduledAction
{
/*
* The search service.
*/
private SearchService searchService;
/*
* The template service.
*/
private TemplateService templateService;
/*
* The query language to use
*/
private String queryLanguage;
/*
* The stores against which the query should run
*/
private List<String> stores;
/*
* The template for the query
*/
private String queryTemplate;
/*
* The cron expression
*/
private String cronExpression;
/*
* The name of the job
*/
private String jobName;
/*
* The job group
*/
private String jobGroup;
/*
* The name of the trigger
*/
private String triggerName;
/*
* The name of the trigger group
*/
private String triggerGroup;
/*
* The scheduler
*/
private Scheduler scheduler;
/*
* The templateModelFactory
*
* This defines in which template language the query template is defined
*/
private TemplateActionModelFactory templateActionModelFactory;
public CronScheduledQueryBasedTemplateActionDefinition()
{
super();
}
//
// IOC
//
public SearchService getSearchService()
{
return searchService;
}
public void setSearchService(SearchService searchService)
{
this.searchService = searchService;
}
public TemplateService getTemplateService()
{
return templateService;
}
public void setTemplateService(TemplateService templateService)
{
this.templateService = templateService;
}
public Scheduler getScheduler()
{
return scheduler;
}
public void setScheduler(Scheduler scheduler)
{
this.scheduler = scheduler;
}
public TemplateActionModelFactory getTemplateActionModelFactory()
{
return templateActionModelFactory;
}
public void setTemplateActionModelFactory(TemplateActionModelFactory templateActionModelFactory)
{
this.templateActionModelFactory = templateActionModelFactory;
}
//
// End of IOC
//
@Override
public Trigger getTrigger()
{
try
{
return new CronTrigger(getTriggerName(), getTriggerGroup(), getCronExpression());
}
catch (ParseException e)
{
throw new InvalidCronExpression("Invalid chron expression: n" + getCronExpression());
}
}
@Override
public List<NodeRef> getNodes()
{
LinkedList<NodeRef> nodeRefs = new LinkedList<NodeRef>();
// Build the actual query string
String queryTemplate = getQueryTemplate();
String query = templateService.processTemplateString(getTemplateActionModelFactory().getTemplateEngine(),
queryTemplate, getTemplateActionModelFactory().getModel());
// Execute the query
SearchParameters sp = new SearchParameters();
sp.setLanguage(getQueryLanguage());
sp.setQuery(query);
for (String storeRef : getStores())
{
sp.addStore(new StoreRef(storeRef));
}
// Transform the reults into a node list
ResultSet results = null;
try
{
results = searchService.query(sp);
for (ResultSetRow row : results)
{
nodeRefs.add(row.getNodeRef());
}
}
finally
{
if (results != null)
{
results.close();
}
}
return nodeRefs;
}
@Override
public Action getAction(NodeRef nodeRef)
{
// Use the template to build its action
return getTemplateActionDefinition().getAction(nodeRef);
}
//
// IOC/Getters/Setters for instance variables
//
public void setQueryLanguage(String queryLanguage)
{
this.queryLanguage = queryLanguage;
}
public String getQueryLanguage()
{
return queryLanguage;
}
public void setStores(List<String> stores)
{
this.stores = stores;
}
public List<String> getStores()
{
return stores;
}
public void setQueryTemplate(String queryTemplate)
{
this.queryTemplate = queryTemplate;
}
public String getQueryTemplate()
{
return queryTemplate;
}
public void setCronExpression(String cronExpression)
{
this.cronExpression = cronExpression;
}
public String getCronExpression()
{
return cronExpression;
}
public void setJobName(String jobName)
{
this.jobName = jobName;
}
public String getJobName()
{
return jobName;
}
public void setJobGroup(String jobGroup)
{
this.jobGroup = jobGroup;
}
public String getJobGroup()
{
return jobGroup;
}
public void setTriggerName(String triggerName)
{
this.triggerName = triggerName;
}
public String getTriggerName()
{
return triggerName;
}
public void setTriggerGroup(String triggerGroup)
{
this.triggerGroup = triggerGroup;
}
public String getTriggerGroup()
{
return this.triggerGroup;
}
/**
* Register with the scheduler.
*/
public void afterPropertiesSet() throws Exception
{
register(getScheduler());
}
}

View File

@@ -0,0 +1,150 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* 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.alfresco.repo.action.scheduled;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import javax.transaction.UserTransaction;
import junit.framework.TestCase;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.datatype.Duration;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper;
import org.alfresco.util.ISO8601DateFormat;
import org.springframework.context.ApplicationContext;
/**
* Test that the correct date ranges are generated for lucene
*
* @author Andy Hind
*/
public class FreeMarkerModelLuceneFunctionTest extends TestCase
{
//private static SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sssZ");
private static SimpleDateFormat SDF2 = new SimpleDateFormat("yyyy-MM-dd");
private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
private AuthenticationComponent authenticationComponent;
private ServiceRegistry serviceRegistry;
private UserTransaction tx;
private Date today;
public FreeMarkerModelLuceneFunctionTest()
{
super();
}
public FreeMarkerModelLuceneFunctionTest(String arg0)
{
super(arg0);
}
public void setUp() throws Exception
{
authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponentImpl");
serviceRegistry = (ServiceRegistry) ctx.getBean("ServiceRegistry");
this.authenticationComponent.setSystemUserAsCurrentUser();
TransactionService transactionService = (TransactionService) ctx.getBean(ServiceRegistry.TRANSACTION_SERVICE
.getLocalName());
tx = transactionService.getUserTransaction();
tx.begin();
GregorianCalendar cal = new GregorianCalendar();
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
today = cal.getTime();
}
@Override
protected void tearDown() throws Exception
{
authenticationComponent.clearCurrentSecurityContext();
tx.rollback();
super.tearDown();
}
public void testDate()
{
String template = "${date?date?string(\"yyyy-MM-dd\")}";
FreeMarkerWithLuceneExtensionsModelFactory mf = new FreeMarkerWithLuceneExtensionsModelFactory();
mf.setServiceRegistry(serviceRegistry);
String result = serviceRegistry.getTemplateService().processTemplateString("freemarker", template, mf.getModel());
assertEquals(result, SDF2.format(new Date()));
}
public void testLuceneDateRangeFunction()
{
String template = "${luceneDateRange(\"2000-01-01T00:00:00.000Z\", \"P1D\")}";
FreeMarkerWithLuceneExtensionsModelFactory mf = new FreeMarkerWithLuceneExtensionsModelFactory();
mf.setServiceRegistry(serviceRegistry);
String result = serviceRegistry.getTemplateService().processTemplateString("freemarker", template, mf.getModel());
assertEquals(result, "[2000-01-01T00:00:00.000Z TO 2000-01-02T00:00:00.000Z]");
}
public void testLuceneDateRangeFunctionToAdte()
{
String template = "${luceneDateRange(\"2000-01-01T00:00:00.000Z\", \"2000-01-05T00:00:00.000Z\")}";
FreeMarkerWithLuceneExtensionsModelFactory mf = new FreeMarkerWithLuceneExtensionsModelFactory();
mf.setServiceRegistry(serviceRegistry);
String result = serviceRegistry.getTemplateService().processTemplateString("freemarker", template, mf.getModel());
assertEquals(result, "[2000-01-01T00:00:00.000Z TO 2000-01-05T00:00:00.000Z]");
}
public void testLuceneDateRangeFunctionTodayPlus4()
{
String template = "${luceneDateRange(today, \"P4D\")}";
FreeMarkerWithLuceneExtensionsModelFactory mf = new FreeMarkerWithLuceneExtensionsModelFactory();
mf.setServiceRegistry(serviceRegistry);
String result = serviceRegistry.getTemplateService().processTemplateString("freemarker", template, mf.getModel());
assertNotNull(result);
assertEquals(result, "["+ISO8601DateFormat.format(today) + " TO " + ISO8601DateFormat.format(Duration.add(today, new Duration("P4D"))) + "]");
}
public void testLuceneDateRangeFunctionTodayMinus4()
{
String template = "${luceneDateRange(today, \"-P4D\")}";
FreeMarkerWithLuceneExtensionsModelFactory mf = new FreeMarkerWithLuceneExtensionsModelFactory();
mf.setServiceRegistry(serviceRegistry);
String result = serviceRegistry.getTemplateService().processTemplateString("freemarker", template, mf.getModel());
assertEquals(result, "["+ ISO8601DateFormat.format(Duration.add(today, new Duration("-P4D"))) + " TO " + ISO8601DateFormat.format(today) + "]");
}
public void testLuceneDateRangeFunctionTodayToday()
{
String template = "${luceneDateRange(today, today)}";
FreeMarkerWithLuceneExtensionsModelFactory mf = new FreeMarkerWithLuceneExtensionsModelFactory();
mf.setServiceRegistry(serviceRegistry);
String result = serviceRegistry.getTemplateService().processTemplateString("freemarker", template, mf.getModel());
assertEquals(result, "["+ISO8601DateFormat.format(today) + " TO " + ISO8601DateFormat.format(today) + "]");
}
}

View File

@@ -0,0 +1,277 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* 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.alfresco.repo.action.scheduled;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.TemplateNode;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.repository.datatype.Duration;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.util.ISO8601DateFormat;
import freemarker.template.TemplateDateModel;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateScalarModel;
/**
* A factory implementation to build suitable models for the freemarker templating language.
*
* @author Andy Hind
*/
public class FreeMarkerWithLuceneExtensionsModelFactory implements TemplateActionModelFactory
{
/*
* Service registry
*/
private ServiceRegistry serviceRegistry;
public FreeMarkerWithLuceneExtensionsModelFactory()
{
super();
}
// IOC
public void setServiceRegistry(ServiceRegistry serviceRegistry)
{
this.serviceRegistry = serviceRegistry;
}
/**
* Get the non-contextual model.
*
* This defines:
* <ol>
* <li>dates: date, today, yesterday, tomorrow
* <li>functions: luceneDateRange, selectSingleNode
* </ol>
*/
public Map<String, Object> getModel()
{
GregorianCalendar cal = new GregorianCalendar();
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
HashMap<String, Object> model = new HashMap<String, Object>();
model.put("date", new Date());
Date today = cal.getTime();
model.put("today", today);
model.put("yesterday", Duration.add(today, new Duration("-P1D")));
model.put("tomorrow", Duration.add(today, new Duration("P1D")));
model.put("luceneDateRange", new LuceneDateRangeFunction());
model.put("selectSingleNode", new QueryForSingleNodeFunction());
return model;
}
/**
* Defines a non-contextual nod model + the contextual node
*/
public Map<String, Object> getModel(NodeRef nodeRef)
{
Map<String, Object> model = getModel();
TemplateNode companyRootNode = new TemplateNode(nodeRef, serviceRegistry, null);
model.put("node", companyRootNode);
return model;
}
/**
* Function to find a single node by query
*
* @author Andy Hind
*/
private class QueryForSingleNodeFunction implements TemplateMethodModelEx
{
public Object exec(List args) throws TemplateModelException
{
if (args.size() == 3)
{
Object arg0 = args.get(0);
Object arg1 = args.get(1);
Object arg2 = args.get(2);
StoreRef storeRef;
String language;
String query;
if (arg0 instanceof TemplateScalarModel)
{
storeRef = new StoreRef(((TemplateScalarModel) arg0).getAsString());
}
else
{
throw new TemplateModelException("Invalid store string");
}
if (arg1 instanceof TemplateScalarModel)
{
language = ((TemplateScalarModel) arg1).getAsString();
}
else
{
throw new TemplateModelException("Invalid language string");
}
if (arg2 instanceof TemplateScalarModel)
{
query = ((TemplateScalarModel) arg2).getAsString();
}
else
{
throw new TemplateModelException("Invalid query string");
}
SearchParameters sp = new SearchParameters();
sp.addStore(storeRef);
sp.setLanguage(language);
sp.setQuery(query);
ResultSet results = serviceRegistry.getSearchService().query(sp);
if (results.length() == 0)
{
throw new TemplateModelException("No nodes selected");
}
else if (results.length() == 1)
{
return results.getNodeRef(0).toString();
}
else
{
throw new TemplateModelException("More than one node selected");
}
}
else
{
throw new TemplateModelException("Incorrect arguments");
}
}
}
/**
* Function to generate the date range portion of a lucene query
*
* @author Andy Hind
*/
private static class LuceneDateRangeFunction implements TemplateMethodModelEx
{
public Object exec(List args) throws TemplateModelException
{
if (args.size() == 2)
{
Object arg0 = args.get(0);
Object arg1 = args.get(1);
Date startDate = null;
Date endDate = null;
if (arg0 instanceof TemplateDateModel)
{
startDate = (Date) ((TemplateDateModel) arg0).getAsDate();
}
else if (arg0 instanceof TemplateScalarModel)
{
String startDateString = ((TemplateScalarModel) arg0).getAsString();
startDate = ISO8601DateFormat.parse(startDateString);
}
else
{
throw new TemplateModelException("Invalid date entry");
}
if (arg1 instanceof TemplateDateModel)
{
endDate = (Date) ((TemplateDateModel) arg0).getAsDate();
}
else if (arg1 instanceof TemplateScalarModel)
{
String valueString = ((TemplateScalarModel) arg1).getAsString();
try
{
Duration duration = new Duration(valueString);
endDate = Duration.add(startDate, duration);
}
catch (Exception e)
{
endDate = ISO8601DateFormat.parse(valueString);
}
}
else
{
throw new TemplateModelException("Invalid date entry");
}
if (startDate.compareTo(endDate) > 0)
{
Date temp = startDate;
startDate = endDate;
endDate = temp;
}
StringBuilder builder = new StringBuilder();
builder.append("[");
builder.append(DefaultTypeConverter.INSTANCE.convert(String.class, startDate));
builder.append(" TO ");
builder.append(DefaultTypeConverter.INSTANCE.convert(String.class, endDate));
builder.append("]");
return builder.toString();
}
else
{
throw new TemplateModelException("Invalid date entry");
}
}
}
/**
* The name of the template engine for which this model applies.
* In this case, "freemarker".
*/
public String getTemplateEngine()
{
return "freemarker";
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* 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.alfresco.repo.action.scheduled;
public class InvalidCronExpression extends ScheduledActionException
{
/**
* Comment for <code>serialVersionUID</code>
*/
private static final long serialVersionUID = -6618964886875008727L;
public InvalidCronExpression(String msgId)
{
super(msgId);
}
public InvalidCronExpression(String msgId, Object[] msgParams)
{
super(msgId, msgParams);
}
public InvalidCronExpression(String msgId, Throwable cause)
{
super(msgId, cause);
}
public InvalidCronExpression(String msgId, Object[] msgParams, Throwable cause)
{
super(msgId, msgParams, cause);
}
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* 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.alfresco.repo.action.scheduled;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.InitializingBean;
/**
* The information needed to schedule a job.
*
* The implementation is responsible for creating job details, triggers and registering with a scheduler.
*
* This is not used anywhere at the moment. When we have a service then scheduled actions will be registered with the service.
*
* @author Andy Hind
*/
public interface ScheduledActionDefinition extends InitializingBean
{
/**
* Set the template action definition that is used to build the Action to execute.
*
* @param templateActionDefinition
*/
public void setTemplateActionDefinition(TemplateActionDefinition templateActionDefinition);
/**
* Get the template action definition that is used to build the Action to execute.
*
* @return
*/
public TemplateActionDefinition getTemplateActionDefinition();
/**
* Register with a scheduler. This should be called in the implementation afterPropertiesSet() method of InitializingBean
*
* @param scheduler
* @throws SchedulerException
*/
public void register(Scheduler scheduler) throws SchedulerException;
/**
* Set the name of the job - used for job admin
*
* @param jobName
*/
public void setJobName(String jobName);
/**
* Get the name of the job - used for job admin
*
* @return
*/
public String getJobName();
/**
* Set the job group - used for job admin
*
* @param jobGroup
*/
public void setJobGroup(String jobGroup);
/**
* Get the job group - used for job admin
* @return
*/
public String getJobGroup();
/**
* Set the trigger name - used for job admin
*
* @param triggerName
*/
public void setTriggerName(String triggerName);
/**
* Get the trigger name - used for job admin
* @return
*/
public String getTriggerName();
/**
* Set the trigger group - used for job admin
*
* @param triggerGroup
*/
public void setTriggerGroup(String triggerGroup);
/**
* Get the trigger group - used for job admin
*
* @return
*/
public String getTriggerGroup();
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* 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.alfresco.repo.action.scheduled;
import org.alfresco.error.AlfrescoRuntimeException;
/**
* Base exception for sceduled actions.
*
* @author Andy Hind
*/
public class ScheduledActionException extends AlfrescoRuntimeException
{
/**
* Comment for <code>serialVersionUID</code>
*/
private static final long serialVersionUID = -543079391770744598L;
public ScheduledActionException(String msgId)
{
super(msgId);
}
public ScheduledActionException(String msgId, Object[] msgParams)
{
super(msgId, msgParams);
}
public ScheduledActionException(String msgId, Throwable cause)
{
super(msgId, cause);
}
public ScheduledActionException(String msgId, Object[] msgParams, Throwable cause)
{
super(msgId, msgParams, cause);
}
}

View File

@@ -0,0 +1,224 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* 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.alfresco.repo.action.scheduled;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.repo.action.executer.ActionExecuter;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ActionDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.namespace.QName;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* This class defines the template used to build a single action.
*
* @author Andy Hind
*/
public class SimpleTemplateActionDefinition extends AbstractTemplateActionDefinition implements ApplicationContextAware
{
/*
* The name of the action
*/
private String actionName;
/*
* The parameters used by the action
*/
private Map<String, String> parameterTemplates;
/*
* The model factory to build models appropriate to the template language used to define
* templated parameters.
*/
private TemplateActionModelFactory templateActionModelFactory;
/*
* The dictionary service.
*/
private DictionaryService dictionaryService;
/*
* The application context
* (Some actions are not publicly exposed via the action service.
* They can always be obtained via the appropriate action excecutor.)
*/
private ApplicationContext applicationContext;
/**
* Simple constructor.
*
*/
public SimpleTemplateActionDefinition()
{
super();
}
/**
* Get the template model factory.
*
* @return
*/
public TemplateActionModelFactory getTemplateActionModelFactory()
{
return templateActionModelFactory;
}
/**
* Set the template model factory IOC.
*
* @param templateActionModelFactory
*/
public void setTemplateActionModelFactory(TemplateActionModelFactory templateActionModelFactory)
{
this.templateActionModelFactory = templateActionModelFactory;
}
/**
* Get the dictionary service.
*
* @return
*/
public DictionaryService getDictionaryService()
{
return dictionaryService;
}
/**
* Set the dictionary service - IOC.
*
* @param dictionaryService
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* Set the name of the action.
*
* @param actionName
*/
public void setActionName(String actionName)
{
this.actionName = actionName;
}
/**
* Get the name of the action.
*
* @return
*/
public String getActionName()
{
return actionName;
}
/**
* Set the map of parameters used by the template.
* These are processed via the template service to produce the actual poarameters.
*
* @param parameterTemplates
*/
public void setParameterTemplates(Map<String, String> parameterTemplates)
{
this.parameterTemplates = parameterTemplates;
}
/**
* Get the templates that define the parameters for the action.
*
* @return
*/
public Map<String, String> getParameterTemplates()
{
return parameterTemplates;
}
/**
* Generate the action from the template using the context node.
*/
public Action getAction(NodeRef nodeRef)
{
// Get the action definition. We can not go to the service are some are not exposed.
// So we find them from the application context.
ActionExecuter actionExecutor = (ActionExecuter)applicationContext.getBean(getActionName());
ActionDefinition actionDefinition = actionExecutor.getActionDefinition();
// Build the base action
Action action = actionService.createAction(getActionName());
// Go through the template definitions and set the values.
for (String paramName : parameterTemplates.keySet())
{
// Transform the template
String template = parameterTemplates.get(paramName);
String stringValue = templateService.processTemplateString(getTemplateActionModelFactory()
.getTemplateEngine(), template, getTemplateActionModelFactory().getModel(nodeRef));
// Find the data type from the action defintion
DataTypeDefinition dataTypeDef;
if (actionDefinition.getParameterDefintion(paramName) != null)
{
dataTypeDef = dictionaryService
.getDataType(actionDefinition.getParameterDefintion(paramName).getType());
}
// Fall back to the DD using the property name of it is not defined
// This is sometimes used for setting a property to a value.
// There can be no definition for such an ad hoc property.
else
{
dataTypeDef = dictionaryService.getProperty(QName.createQName(paramName)).getDataType();
}
// Convert the template result into the correct type and set the parameter
Object value = DefaultTypeConverter.INSTANCE.convert(dataTypeDef, stringValue);
if (value instanceof Serializable)
{
action.setParameterValue(paramName, (Serializable) value);
}
}
// If there is a compensating action then set it.
if (getCompensatingTemplateCompositeActionDefinition() != null)
{
action.setCompensatingAction(getCompensatingTemplateCompositeActionDefinition().getAction(nodeRef));
}
return action;
}
/**
* ApplciationContextAware - get the application context.
*/
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
this.applicationContext = applicationContext;
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* 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.alfresco.repo.action.scheduled;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* A template action definition is used to generate an action from a template style
* definition.
*
* @author Andy Hind
*/
public interface TemplateActionDefinition
{
/**
* Generate an action definition for the action defined by this template.
*
* @param nodeRef
* @return
*/
public Action getAction(NodeRef nodeRef);
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* 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.alfresco.repo.action.scheduled;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* A factory that builds models to use with a particular template engine for use with scheduled actions built
* from action templates.
*
* @author Andy Hind
*/
public interface TemplateActionModelFactory
{
/**
* Get the name of the template engine for which this factory applies
*
* @return
*/
public String getTemplateEngine();
/**
* Build a model with no default node context.
*
* @return
*/
public Object getModel();
/**
* Build a model with a default node context.
*
* @param nodeRef
* @return
*/
public Object getModel(NodeRef nodeRef);
}