/** * Copyright 2010 JBoss Inc * * 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. */ /* * 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. * under the License. */ package org.drools.camel.component; import java.net.URISyntaxException; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.camel.Consumer; import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.RuntimeCamelException; import org.apache.camel.impl.DefaultEndpoint; import org.apache.camel.impl.DefaultExchange; import org.apache.camel.impl.DefaultMessage; import org.apache.camel.spi.DataFormat; import org.drools.command.impl.CommandBasedStatefulKnowledgeSession; import org.drools.core.util.StringUtils; import org.drools.grid.GridNode; import org.drools.impl.KnowledgeBaseImpl; import org.drools.impl.StatefulKnowledgeSessionImpl; import org.drools.impl.StatelessKnowledgeSessionImpl; import org.drools.reteoo.ReteooRuleBase; import org.drools.runtime.CommandExecutor; public class DroolsEndpoint extends DefaultEndpoint { /** * An ENUM to define which action should be executed by the * producer into this end point */ public static enum Action { EXECUTE("execute"), INSERT_BODY("insertBody"), INSERT_MESSAGE("insertMessage"), INSERT_EXCHANGE("insertExchange"); private final String id; Action(String id) { this.id = id; } public String getId() { return this.id; } public static Action resolveAction(String id) { if ( EXECUTE.getId().equalsIgnoreCase( id ) ) { return EXECUTE; } else if ( INSERT_BODY.getId().equalsIgnoreCase( id ) ) { return INSERT_BODY; } else if ( INSERT_MESSAGE.getId().equalsIgnoreCase( id ) ) { return INSERT_MESSAGE; } else if ( INSERT_EXCHANGE.getId().equalsIgnoreCase( id ) ) { return INSERT_EXCHANGE; } else { throw new IllegalArgumentException( "Invalid action configuring EndPoint = " + id ); } } } public static final Pattern p = Pattern.compile( "[\"']?lookup[\"']?\\s*[:=]\\s*[\"']([^\"']+)[\"']" ); public String ksessionId; public CommandExecutor executor; public GridNode node; public String dataFormatName; public DataFormat dataFormat; public Action action = Action.EXECUTE; public String entryPoint = null; public String channel = null; public DroolsEndpoint(String endpointUri, String remaining, DroolsComponent component) throws URISyntaxException { super( endpointUri, component ); configure( component, remaining ); } public Consumer createConsumer(Processor processor) throws Exception { return new DroolsConsumer( this, processor ); } public Producer createProducer() throws Exception { if ( Action.EXECUTE.equals( action ) ) { return new DroolsExecuteProducer( this, node ); } else { return new DroolsInsertProducer( this, node ); } } public boolean isSingleton() { return true; } public String getKsessionId() { return ksessionId; } public void setKsessionId(String ksession) { this.ksessionId = ksession; } public CommandExecutor getExecutor() { return executor; } public GridNode getGridNode() { return node; } protected void configure(DroolsComponent component, String uri) { String nodeId = getExecuteNodeId( uri ); ksessionId = getKsessionId( uri ); if ( !StringUtils.isEmpty( nodeId ) ) { // let's look it up node = component.getCamelContext().getRegistry().lookup( nodeId, GridNode.class ); if ( node == null ) { throw new RuntimeCamelException( "Could not find GridNode for uri=\"" + uri + "\" in CamelContext. Check configuration." ); } // if id is empty this endpoint is not attached to a CommandExecutor and will have to look it up at runtime. if ( !StringUtils.isEmpty( ksessionId ) ) { // lookup command executor executor = node.get( ksessionId, CommandExecutor.class ); if ( executor == null ) { throw new RuntimeCamelException( "Failed to instantiate DroolsEndpoint. " + "Lookup of CommandExecutor with uri=\"" + uri + "\" failed. Check configuration." ); } } } else { // this is a hanging entity, not attached to an ExecutionNode executor = component.getCamelContext().getRegistry().lookup( ksessionId, CommandExecutor.class ); if ( executor == null ) { throw new RuntimeCamelException( "Failed to instantiate DroolsEndpoint. Could not find ksession for " + " uri=\"" + uri + "\". Check configuration." ); } // TODO: test this scenario... } // if ( !StringUtils.isEmpty( getDataFormat() ) ) { // String dataFormatName = getDataFormat(); // if ( "drools-xstream".equals( dataFormatName ) ) { // XStreamDataFormat xstreaDataFormat = new XStreamDataFormat(); // xstreaDataFormat.setXStream( BatchExecutionHelper.newXStreamMarshaller() ); // this.dataFormat = xstreaDataFormat; // } else if ( "drools-json".equals( dataFormatName ) ) { // JsonDataFormat xstreaDataFormat = new JsonDataFormat(); // xstreaDataFormat.setXStream( BatchExecutionHelper.newJSonMarshaller() ); // this.dataFormat = xstreaDataFormat; // } else if ( "jaxb".equals( dataFormatName ) ) { // // to specify jaxb must be // //JaxbDataFormat jaxbDataFormat = new JaxbDataFormat(); // //jaxbDataFormat.setContextPath( contextPath ) // } else { // this.dataFormat = getCamelContext().getRegistry().lookup( getDataFormat(), // DataFormat.class ); // } // } } public static final String getExecuteNodeId(String uri) { int pos = uri.indexOf( '/' ); return (pos < 0) ? uri : uri.substring( 0, pos ); } public static final String getKsessionId(String uri) { int pos = uri.indexOf( '/' ); return (pos < 0) ? "" : uri.substring( pos + 1 ); } public String getDataFormat() { return this.dataFormatName; } public void setDataFormat(String dataFormatName) { this.dataFormatName = dataFormatName; } public String getLookup(String body) { Matcher m = p.matcher( body ); String name = null; if ( m.find() ) { name = m.group( 1 ); } return name; } public CommandExecutor getCommandExecutor(String name) { if ( this.executor != null ) { return this.executor; } if ( this.node == null ) { throw new RuntimeException( "ExecutionNode for CommandExecutor lookup cannot be null" ); } return node.get( name, CommandExecutor.class ); } public ClassLoader getClassLoader(CommandExecutor exec) { ClassLoader cl = null; if ( exec instanceof StatefulKnowledgeSessionImpl ) { cl = ((ReteooRuleBase) ((StatefulKnowledgeSessionImpl) exec).getRuleBase()).getRootClassLoader(); } else if ( exec instanceof StatelessKnowledgeSessionImpl ) { cl = ((ReteooRuleBase) ((StatelessKnowledgeSessionImpl) exec).getRuleBase()).getRootClassLoader(); } else if ( exec instanceof CommandBasedStatefulKnowledgeSession ) { cl = ((ReteooRuleBase) ((KnowledgeBaseImpl) ((CommandBasedStatefulKnowledgeSession) exec).getKnowledgeBase()).getRuleBase()).getRootClassLoader(); } return cl; } public Action getAction() { return action; } public void setAction(Action action) { this.action = action; } public void setAction(String action) { this.action = Action.resolveAction( action ); } public String getEntryPoint() { return entryPoint; } public void setEntryPoint(String entryPoint) { this.entryPoint = entryPoint; } public String getChannel() { return channel; } public void setChannel(String channel) { this.channel = channel; } public Exchange createExchange( Object pojo ) { DefaultMessage msg = new DefaultMessage(); msg.setBody( pojo ); DefaultExchange exchange = new DefaultExchange(this, getExchangePattern()); exchange.setIn( msg ); return exchange; } }