/* * (C) Copyright Factory4Solutions a.s. 2009 * * Licensed 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.sculptor.framework.drools; /** * This advice should be used to wave Drools to service calls * * @author Ing. Pavel Tavoda */ import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.Iterator; import java.util.List; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.kie.api.command.Command; import org.kie.internal.agent.KnowledgeAgent; import org.kie.internal.agent.KnowledgeAgentFactory; import org.kie.internal.command.CommandFactory; import org.kie.internal.io.ResourceChangeScannerConfiguration; import org.kie.internal.io.ResourceFactory; import org.kie.internal.runtime.StatelessKnowledgeSession; import org.sculptor.framework.context.ServiceContext; import org.sculptor.framework.context.ServiceContextStore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class DroolsAdvice implements MethodInterceptor, ApplicationContextAware { private static final Logger log = LoggerFactory.getLogger(DroolsAdvice.class); private ApplicationContext appContext; private KnowledgeAgent kagent; int updateInterval=300; // 5 min String ruleSet="/CompanyPolicy.xml"; boolean catchAllExceptions=false; public Object invoke(MethodInvocation procJointpoint) throws Throwable { long startTimeExec=System.currentTimeMillis(); log.info("############# START DROOLS RULES"); RequestDescription req=new RequestDescription( procJointpoint); try { Object[] arguments = procJointpoint.getArguments(); ServiceContext ctx; int startArg; if (arguments[0] instanceof ServiceContext) { ctx=(ServiceContext) arguments[0]; startArg=1; } else { ctx=ServiceContextStore.get(); startArg=0; } HashMap<String, Object> objects=new HashMap<String, Object>(); for (int i=startArg; i < arguments.length; i++) { objects.put("arg"+i, arguments[i]); } objects.put("request", req); objects.put("service", procJointpoint.getThis()); objects.put("username", ServiceContextStore.getCurrentUser()); HashMap<String, Object> globals=new HashMap<String, Object>(); if (ctx != null) { globals.put("serviceContext", ctx); } globals.put("appContext", appContext); globals.put("log", log); Calendar curDate = Calendar.getInstance(); globals.put("currentDate", curDate); globals.put("currentTimestamp", curDate.getTimeInMillis()); applyCompanyPolicy(objects, globals); } catch (Throwable th) { if (catchAllExceptions) { while(th.getCause() != null) { th=th.getCause(); } log.warn("Applying company policy finished with error: "+th.getMessage(), th); } else { throw th; } } finally { log.info("############# END DROOLS RULES ("+(System.currentTimeMillis() - startTimeExec)+" ms)"); } if (req.wasProceed() && req.getLastResult() != null && req.getLastResult() instanceof Throwable) { throw (Throwable) req.getLastResult(); } else if (req.wasProceed()) { return req.getLastResult(); } else { return procJointpoint.proceed(); } } private void applyCompanyPolicy(HashMap<String, Object> objects, HashMap<String, Object> globals) { if (kagent==null) { synchronized (DroolsAdvice.class) { if (kagent==null) { KnowledgeAgent unconfigAgent = KnowledgeAgentFactory.newKnowledgeAgent( "CompanyPolicyAgent" ); unconfigAgent.applyChangeSet(ResourceFactory.newClassPathResource(getDroolsRuleSet())); ResourceChangeScannerConfiguration sconf = ResourceFactory.getResourceChangeScannerService().newResourceChangeScannerConfiguration(); sconf.setProperty( "drools.resource.scanner.interval", Integer.toString(getUpdateInterval()) ); ResourceFactory.getResourceChangeScannerService().configure( sconf ); ResourceFactory.getResourceChangeNotifierService().start(); ResourceFactory.getResourceChangeScannerService().start(); kagent = unconfigAgent; } } } StatelessKnowledgeSession slSession = kagent.newStatelessKnowledgeSession(); List<Command<?>> cmds = new ArrayList<Command<?>>(); if (globals != null && globals.size() > 0) { for (Iterator<String> keys=globals.keySet().iterator(); keys.hasNext();) { String key=keys.next(); cmds.add(CommandFactory.newSetGlobal(key, globals.get(key))); } } if (objects != null && objects.size() > 0) { for (Iterator<String> keys=objects.keySet().iterator(); keys.hasNext();) { String key=keys.next(); cmds.add( CommandFactory.newInsert(objects.get(key), key) ); } } // For stateless sesion is automatic // cmds.add(CommandFactory.newFireAllRules()); slSession.execute( CommandFactory.newBatchExecution( cmds ) ); } public int getUpdateInterval() { return updateInterval; } public void setUpdateInterval(int updateInterval) { this.updateInterval = updateInterval; } public String getDroolsRuleSet() { return ruleSet; } public void setDroolsRuleSet(String ruleSet) { this.ruleSet = ruleSet; } public boolean getCatchAllExceptions() { return catchAllExceptions; } public void setCatchAllExceptions(boolean catchAllExceptions) { this.catchAllExceptions = catchAllExceptions; } /** * Dependency injection, ApplicationContextAware. */ public void setApplicationContext(ApplicationContext appContext) throws BeansException { this.appContext=appContext; } }