001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.servicemix.drools.model;
018    
019    import javax.jbi.component.ComponentContext;
020    import javax.jbi.messaging.DeliveryChannel;
021    import javax.jbi.messaging.ExchangeStatus;
022    import javax.jbi.messaging.Fault;
023    import javax.jbi.messaging.InOnly;
024    import javax.jbi.messaging.MessageExchange;
025    import javax.jbi.messaging.MessagingException;
026    import javax.jbi.messaging.NormalizedMessage;
027    import javax.jbi.messaging.RobustInOnly;
028    import javax.xml.transform.Source;
029    
030    import org.apache.commons.logging.Log;
031    import org.apache.commons.logging.LogFactory;
032    import org.apache.servicemix.JbiConstants;
033    import org.apache.servicemix.client.ServiceMixClient;
034    import org.apache.servicemix.client.ServiceMixClientFacade;
035    import org.apache.servicemix.common.EndpointSupport;
036    import org.apache.servicemix.drools.DroolsComponent;
037    import org.apache.servicemix.drools.DroolsEndpoint;
038    import org.apache.servicemix.jbi.jaxp.SourceTransformer;
039    import org.apache.servicemix.jbi.jaxp.StringSource;
040    import org.apache.servicemix.jbi.resolver.URIResolver;
041    import org.apache.servicemix.jbi.util.MessageUtil;
042    import org.drools.FactHandle;
043    import org.drools.WorkingMemory;
044    import org.drools.event.ActivationCreatedEvent;
045    import org.drools.event.DefaultAgendaEventListener;
046    
047    /**
048     * A helper class for use inside a rule to forward a message to an endpoint
049     * 
050     * @version $Revision: 426415 $
051     */
052    public class JbiHelper extends DefaultAgendaEventListener {
053    
054        private DroolsEndpoint endpoint;
055        private Exchange exchange;
056        private WorkingMemory memory;
057        private FactHandle exchangeFactHandle;
058        private int rulesFired;
059        private boolean exchangeHandled;
060    
061        public JbiHelper(DroolsEndpoint endpoint, MessageExchange exchange, WorkingMemory memory) {
062            this.endpoint = endpoint;
063            this.exchange = new Exchange(exchange, endpoint.getNamespaceContext());
064            this.memory = memory;
065            
066            this.memory.addEventListener(this);
067            this.exchangeFactHandle = this.memory.assertObject(this.exchange);
068            
069            
070        }
071    
072        public DroolsEndpoint getEndpoint() {
073            return endpoint;
074        }
075    
076        public ComponentContext getContext() {
077            return endpoint.getContext();
078        }
079    
080        public DeliveryChannel getChannel() throws MessagingException {
081            return getContext().getDeliveryChannel();
082        }
083    
084        public ServiceMixClient getClient() {
085            return new ServiceMixClientFacade(getContext());
086        }
087    
088        public Exchange getExchange() {
089            return exchange;
090        }
091    
092        public Log getLogger() {
093            return LogFactory.getLog(memory.getRuleBase().getPackages()[0].getName());
094        }
095    
096        /**
097         * Forwards the inbound message to the given
098         * 
099         * @param uri
100         * @param localPart
101         */
102        /*
103         * public void forward(String uri) throws MessagingException { if (exchange
104         * instanceof InOnly || exchange instanceof RobustInOnly) { MessageExchange
105         * me =
106         * getChannel().createExchangeFactory().createExchange(exchange.getPattern
107         * ()); URIResolver.configureExchange(me, getContext(), uri);
108         * MessageUtil.transferToIn(in, me); getChannel().sendSync(me); } else {
109         * throw new
110         * MessagingException("Only InOnly and RobustInOnly exchanges can be forwarded"
111         * ); } }
112         */
113        public void route(String uri) throws MessagingException {
114            routeTo(null, uri);
115        }
116    
117        public void routeTo(String content, String uri) throws MessagingException {
118            MessageExchange me = this.exchange.getInternalExchange();
119            NormalizedMessage in = null;
120            if (content == null) {
121                in = me.getMessage("in");
122            } else {
123                in = me.createMessage();
124                in.setContent(new StringSource(content));
125            }
126            MessageExchange newMe = getChannel().createExchangeFactory().createExchange(me.getPattern());
127            URIResolver.configureExchange(newMe, getContext(), uri);
128            MessageUtil.transferToIn(in, newMe);
129            // Set the sender endpoint property
130            String key = EndpointSupport.getKey(endpoint);
131            newMe.setProperty(JbiConstants.SENDER_ENDPOINT, key);
132            newMe.setProperty(JbiConstants.CORRELATION_ID, DroolsEndpoint.getCorrelationId(this.exchange.getInternalExchange()));
133            newMe.setProperty(DroolsComponent.DROOLS_CORRELATION_ID, me.getExchangeId());
134            getChannel().send(newMe);
135        }
136    
137        public void routeToDefault(String content) throws MessagingException {
138            routeTo(content, endpoint.getDefaultRouteURI());
139        }
140    
141        /**
142         * This method allows for an asynchronous send().  
143         * It has no error handling support or support for InOut/InOptionalOut MEPs.
144         * 
145         * @param content
146         * @param uri
147         * @throws MessagingException
148         */
149        @Deprecated
150        public void sendTo(String content, String uri) throws MessagingException {
151    
152            MessageExchange me = this.exchange.getInternalExchange();
153    
154            if ((me instanceof InOnly) || (me instanceof RobustInOnly)) {
155                NormalizedMessage in = null;
156                if (content == null) {
157                    in = me.getMessage("in");
158                } else {
159                    in = me.createMessage();
160                    in.setContent(new StringSource(content));
161                }
162                MessageExchange newMe = getChannel().createExchangeFactory().createExchange(me.getPattern());
163                URIResolver.configureExchange(newMe, getContext(), uri);
164                MessageUtil.transferToIn(in, newMe);
165    
166                // If i am in route method could send back the done
167                me.setStatus(ExchangeStatus.DONE);
168                getChannel().send(me);
169    
170                // And send forward the new me
171                getChannel().send(newMe);
172                update();
173            } else {
174                throw new IllegalStateException("sendTo() method should be used for InOnly or RobustInOnly");
175            }
176    
177        }
178    
179        public void fault(String content) throws Exception {
180            fault(new StringSource(content));
181        }
182        /**
183         * Send a JBI Error message (for InOnly) or JBI Fault message (for the other MEPs)
184         * 
185         * @param content the error content
186         * @throws Exception
187         */
188        public void fault(Source content) throws Exception {
189            MessageExchange me = this.exchange.getInternalExchange();
190            if (me instanceof InOnly) {
191                me.setError(new Exception(new SourceTransformer().toString(content)));
192                getChannel().send(me);
193            } else {
194                Fault fault = me.createFault();
195                fault.setContent(content);
196                me.setFault(fault);
197                getChannel().send(me);
198            }
199            exchangeHandled = true;
200        }
201    
202        public void answer(String content) throws Exception {
203            answer(new StringSource(content));
204        }
205        
206        /**
207         * Answer the exchange with the given response content
208         * 
209         * @param content the response
210         * @throws Exception
211         */    
212        public void answer(Source content) throws Exception {
213            MessageExchange me = this.exchange.getInternalExchange();
214            NormalizedMessage out = me.createMessage();
215            out.setContent(content);
216            me.setMessage(out, "out");
217            getChannel().sendSync(me);
218            exchangeHandled = true;
219            update();
220        }
221    
222        public void update() {
223            this.memory.modifyObject(this.exchangeFactHandle, this.exchange);
224        }
225        
226        /**
227         * Get the number of rules that were fired
228         * 
229         * @return the number of rules
230         */
231        public int getRulesFired() {
232            return rulesFired;
233        }
234        
235        /**
236         * Has the MessageExchange been handled by the drools endpoint?
237         * 
238         * @return
239         */
240        
241        public boolean isExchangeHandled() {
242            return exchangeHandled;
243        }
244    
245    
246        // event handler callbacks
247        @Override
248        public void activationCreated(ActivationCreatedEvent event) {
249            rulesFired++;
250        }
251    
252    }