Package org.drools.camel.component

Source Code of org.drools.camel.component.DroolsPolicy$DroolsProcess

/*
* 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.
*/

package org.drools.camel.component;

import java.io.ByteArrayInputStream;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.camel.Exchange;
import org.apache.camel.ExchangePattern;
import org.apache.camel.Message;
import org.apache.camel.Processor;
import org.apache.camel.component.cxf.CxfConstants;
import org.apache.camel.component.cxf.CxfSpringEndpoint;
import org.apache.camel.model.BeanDefinition;
import org.apache.camel.model.DataFormatDefinition;
import org.apache.camel.model.MarshalDefinition;
import org.apache.camel.model.ProcessorDefinition;
import org.apache.camel.model.RouteDefinition;
import org.apache.camel.model.ToDefinition;
import org.apache.camel.model.UnmarshalDefinition;
import org.apache.camel.model.dataformat.JaxbDataFormat;
import org.apache.camel.model.dataformat.XStreamDataFormat;
import org.apache.camel.spi.Policy;
import org.apache.camel.spi.RouteContext;
import org.drools.command.runtime.BatchExecutionCommandImpl;
import org.drools.command.runtime.GetGlobalCommand;
import org.drools.command.runtime.SetGlobalCommand;
import org.drools.command.runtime.process.AbortWorkItemCommand;
import org.drools.command.runtime.process.CompleteWorkItemCommand;
import org.drools.command.runtime.process.SignalEventCommand;
import org.drools.command.runtime.process.StartProcessCommand;
import org.drools.command.runtime.rule.FireAllRulesCommand;
import org.drools.command.runtime.rule.GetObjectsCommand;
import org.drools.command.runtime.rule.InsertElementsCommand;
import org.drools.command.runtime.rule.InsertObjectCommand;
import org.drools.command.runtime.rule.ModifyCommand;
import org.drools.command.runtime.rule.ModifyCommand.SetterImpl;
import org.drools.command.runtime.rule.QueryCommand;
import org.drools.command.runtime.rule.RetractCommand;
import org.drools.common.DefaultFactHandle;
import org.drools.core.util.StringUtils;
import org.drools.jax.soap.PostCxfSoapProcessor;
import org.drools.jax.soap.PostCxfTransportSoapProcessor;
import org.drools.jax.soap.PreCxfSoapProcessor;
import org.drools.jax.soap.PreCxfTransportSoapProcessor;
import org.drools.runtime.CommandExecutor;
import org.drools.runtime.impl.ExecutionResultImpl;
import org.drools.runtime.rule.impl.FlatQueryResults;
import org.drools.xml.jaxb.util.JaxbListWrapper;

public class DroolsPolicy
    implements
    Policy {
    private static boolean augmented;

    public void beforeWrap(RouteContext routeContext,
                           ProcessorDefinition<?> processorDefinition) {
        augmentNodes( routeContext,
                      processorDefinition,
                      new HashSet<Object>() );
    }

    public Processor wrap(RouteContext routeContext,
                          Processor processor) {
        RouteDefinition routeDef = routeContext.getRoute();

        ToDefinition toDrools = getDroolsNode( routeDef );

        Processor returnedProcessor;
        if ( toDrools != null ) {
            returnedProcessor = new DroolsProcess( toDrools.getUri(),
                                                   processor );
        } else {
            returnedProcessor = processor;//new DroolsClientProcessor( processor );
        }
        return returnedProcessor;
    }

    private ToDefinition getDroolsNode(RouteDefinition routeDef) {
        ToDefinition toDrools = null;
        for ( ProcessorDefinition<?> child : routeDef.getOutputs() ) {
            toDrools = getDroolsNode( child );
            if ( toDrools != null ) {
                break;
            }
        }
        return toDrools;
    }

    public static void augmentNodes(RouteContext routeContext,
                                    ProcessorDefinition<?> nav,
                                    Set visited) {
        if ( !nav.getOutputs().isEmpty() ) {

            List<ProcessorDefinition> outputs = nav.getOutputs();
            for ( int i = 0; i < outputs.size(); i++ ) {
                ProcessorDefinition child = outputs.get( i );//it.next();
                if ( child instanceof ToDefinition ) {
                    ToDefinition to = (ToDefinition) child;
                    if ( to.getUri().startsWith( "cxfrs" ) && !visited.contains( to ) ) {
                        BeanDefinition beanDef = new BeanDefinition();
                        beanDef.setBeanType( PreCxfrs.class );
                        outputs.add( i,
                                     beanDef ); // insert before cxfrs
                        beanDef = new BeanDefinition();
                        beanDef.setBeanType( PostCxfrs.class );
                        outputs.add( i + 2,
                                     beanDef ); // insert after cxfrs
                        i = i + 2;// adjust for the two inserts
                    } else if ( to.getUri().startsWith( "cxf" ) && !visited.contains( to ) ) {
                        BeanDefinition beanDef = new BeanDefinition();
                        beanDef.setBeanType( PreCxfSoapProcessor.class );
                        outputs.add( i,
                                     beanDef ); // insert before cxf
                        beanDef = new BeanDefinition();
                        beanDef.setBeanType( PostCxfSoapProcessor.class );
                        outputs.add( i + 2,
                                     beanDef ); // insert after cxf
                        i = i + 2;// adjust for the two inserts
                        augmented = true;
                    }
                } else if ( child instanceof MarshalDefinition ) {
                    MarshalDefinition m = (MarshalDefinition) child;
                    DataFormatDefinition dformatDefinition = m.getDataFormatType();
                    dformatDefinition = processDataFormatType( routeContext,
                                                               m.getRef(),
                                                               dformatDefinition );
                    m.setDataFormatType( dformatDefinition ); // repoint the marshaller, if it was cloned
                } else if ( child instanceof UnmarshalDefinition ) {
                    UnmarshalDefinition m = (UnmarshalDefinition) child;
                    DataFormatDefinition dformatDefinition = m.getDataFormatType();
                    dformatDefinition = processDataFormatType( routeContext,
                                                               m.getRef(),
                                                               dformatDefinition );
                    m.setDataFormatType( dformatDefinition ); // repoint the marshaller, if it was cloned                   
                }
            }

            for ( Iterator<ProcessorDefinition> it = nav.getOutputs().iterator(); it.hasNext(); ) {
                ProcessorDefinition child = it.next();
                augmentNodes( routeContext,
                              child,
                              visited );
            }
        }
    }

    private static DataFormatDefinition processDataFormatType(RouteContext routeContext,
                                                              String ref,
                                                              DataFormatDefinition dformatDefinition) {
        if ( dformatDefinition == null ) {
            if ( "json".equals( ref ) ) {
                dformatDefinition = new XStreamDataFormat();
                ((XStreamDataFormat) dformatDefinition).setDriver( "json" );
            } else if ( "xstream".equals( ref ) ) {
                dformatDefinition = new XStreamDataFormat();
            } else if ( "jaxb".equals( ref ) ) {
                dformatDefinition = new JaxbDataFormat();
            } else {
                dformatDefinition = routeContext.getCamelContext().resolveDataFormatDefinition( ref );
            }
        }

        // always clone before changing
        dformatDefinition = new FastCloner().deepClone( dformatDefinition );

        if ( dformatDefinition instanceof JaxbDataFormat ) {
            dformatDefinition = augmentJaxbDataFormatDefinition( (JaxbDataFormat) dformatDefinition );
        } else if ( dformatDefinition instanceof XStreamDataFormat ) {
            XStreamDataFormat xstreamDataFormat = (XStreamDataFormat) dformatDefinition;
            if ( "json".equals( xstreamDataFormat.getDriver() ) ) {
                dformatDefinition = XStreamJson.newJSonMarshaller( xstreamDataFormat );;
            } else {
                dformatDefinition = XStreamXml.newXStreamMarshaller( (XStreamDataFormat) dformatDefinition );
            }

        }
        return dformatDefinition;
    }

    private ToDefinition getDroolsNode(ProcessorDefinition nav) {
        if ( !nav.getOutputs().isEmpty() ) {
            List<ProcessorDefinition> children = nav.getOutputs();
            for ( ProcessorDefinition child : children ) {
                if ( child instanceof ToDefinition ) {
                    ToDefinition to = (ToDefinition) child;
                    if ( to.getUri().trim().startsWith( "drools:" ) ) {
                        return to;
                    }
                }
                getDroolsNode( child );
            }
        }
        return null;
    }

    /**
     * Clones the passed JaxbDataFormat and then augments it with with Drools related namespaces
     *
     * @param jaxbDataFormat
     * @return
     */
    public static JaxbDataFormat augmentJaxbDataFormatDefinition(JaxbDataFormat jaxbDataFormat) {
        Set<String> set = new HashSet<String>();

        for ( String clsName : JAXB_ANNOTATED_CMD ) {
            set.add( clsName.substring( 0,
                                        clsName.lastIndexOf( '.' ) ) );
        }

        StringBuilder sb = new StringBuilder();
        sb.append( jaxbDataFormat.getContextPath() );
        sb.append( ":" );
        for ( String pkgName : set ) {
            sb.append( pkgName );
            sb.append( ':' );
        }

        jaxbDataFormat.setContextPath( sb.toString() );
        return jaxbDataFormat;
    }

    public static class DroolsClientProcessor
        implements
        Processor {

        private Processor processor;

        public DroolsClientProcessor(Processor processor) {
            this.processor = processor;
        }

        public void process(Exchange exchange) throws Exception {
            exchange.setPattern( ExchangePattern.InOut );
            Message inMessage = exchange.getIn();
            inMessage.setHeader( CxfConstants.CAMEL_CXF_RS_USING_HTTP_API,
                                 Boolean.TRUE );
            inMessage.setHeader( Exchange.HTTP_METHOD,
                                 "POST" );
            inMessage.setHeader( Exchange.HTTP_PATH,
                                 "/execute" );
            inMessage.setHeader( Exchange.ACCEPT_CONTENT_TYPE,
                                 "text/plain" );
            inMessage.setHeader( Exchange.CONTENT_TYPE,
                                 "text/plain" );

            this.processor.process( exchange );
        }

    }

    public static class DroolsProcess
        implements
        Processor {

        private String         droolsUri;
        private DroolsEndpoint dep;
        private Processor      processor;

        public DroolsProcess(String droolsUri,
                             Processor processor) {
            this.droolsUri = droolsUri;
            this.processor = processor;
        }

        public void process(Exchange exchange) throws Exception {
            //Bad Hack - Need to remote it and fix it in Camel (if it's a camel problem)
            //I need to copy the body of the exachange because for some reason
            // the getContext().getEndpoint() erase the content/or loose the reference
            String body = exchange.getIn().getBody( String.class );
            if ( dep == null ) {
               
                this.dep = exchange.getContext().getEndpoint( this.droolsUri,
                                                              DroolsEndpoint.class );
            }

            if ( dep == null ) {
                throw new RuntimeException( "Could not find DroolsEndPoint for uri=" + this.droolsUri );
            }

            ClassLoader originalClassLoader = null;
            try {
                originalClassLoader = Thread.currentThread().getContextClassLoader();

                CommandExecutor exec = dep.executor;
                if ( exec == null ) {
                    String lookup = exchange.getIn().getHeader( DroolsComponent.DROOLS_LOOKUP,
                                                                String.class );
                    if ( StringUtils.isEmpty( lookup ) ) {
                        //Bad Hack - Need to remote it and fix it in Camel (if it's a camel problem)
                        lookup = dep.getLookup( body );
                        //lookup = dep.getLookup( exchange.getIn().getBody( String.class ) );
                    }

                    if ( StringUtils.isEmpty( lookup ) ) {
                        throw new RuntimeException( "No Executor defined and no lookup information available for uri " + this.dep.getEndpointUri() );
                    }
                    exec = dep.getCommandExecutor( lookup );
                }

                if ( exec == null ) {
                    throw new RuntimeException( "CommandExecutor cannot be found for uri " + this.dep.getEndpointUri() );
                }
                ClassLoader localClassLoader = dep.getClassLoader( exec );
                if ( localClassLoader == null ) {
                    throw new RuntimeException( "CommandExecutor Classloader cannot be null for uri " + this.dep.getEndpointUri() );
                }

                // Set the classloader to the one used by the CommandExecutor
                Thread.currentThread().setContextClassLoader( localClassLoader );
                ExecutionNodePipelineContextImpl context = new ExecutionNodePipelineContextImpl( dep.node,
                                                                                                 localClassLoader );
                context.setCommandExecutor( exec );

                exchange.setProperty( "drools-context",
                                      context );
                //Bad Hack - Need to remote it and fix it in Camel (if it's a camel problem)
                // I need to re set the Body because the exchange loose the content at
                // the begining of the method
                 exchange.getIn().setBody(new ByteArrayInputStream(body.getBytes("UTF-8")));

                boolean soap = false;
                if ( !augmented && exchange.getFromEndpoint() instanceof CxfSpringEndpoint ) {
                    new PreCxfTransportSoapProcessor().process( exchange );
                    soap = true;
                }
                    processor.process( exchange );
                if ( soap ) {
                    new PostCxfTransportSoapProcessor().process( exchange );
                }
            } finally {
                Thread.currentThread().setContextClassLoader( originalClassLoader );
            }
        }
    }

    public static final String[] JAXB_ANNOTATED_CMD = {BatchExecutionCommandImpl.class.getName(), SetGlobalCommand.class.getName(), GetGlobalCommand.class.getName(), FireAllRulesCommand.class.getName(), InsertElementsCommand.class.getName(),
                                                    InsertObjectCommand.class.getName(), ModifyCommand.class.getName(), SetterImpl.class.getName(), QueryCommand.class.getName(), RetractCommand.class.getName(), AbortWorkItemCommand.class.getName(),
            SignalEventCommand.class.getName(),
                                                    StartProcessCommand.class.getName(), BatchExecutionCommandImpl.class.getName(), ExecutionResultImpl.class.getName(), DefaultFactHandle.class.getName(), JaxbListWrapper.class.getName(),
                                                    FlatQueryResults.class.getName(), CompleteWorkItemCommand.class.getName(), GetObjectsCommand.class.getName()};

}
TOP

Related Classes of org.drools.camel.component.DroolsPolicy$DroolsProcess

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.