PageRenderTime 62ms CodeModel.GetById 42ms app.highlight 16ms RepoModel.GetById 0ms app.codeStats 1ms

/contrib-fort/rules4jbi/src/main/org/openesb/components/rules4jbi/engine/component/Rules4JBIComponent.java

https://bitbucket.org/pymma/openesb-components
Java | 365 lines | 198 code | 102 blank | 65 comment | 21 complexity | 9607a9a1aa4415eadb596d9e24d953bb MD5 | raw file
  1/*
  2 * @(#)Rules4JBIComponent.java        $Revision: 1.2 $ $Date: 2008/07/14 16:30:26 $
  3 * 
  4 * Copyright (c) 2008 Milan Fort (http://www.milanfort.com/). All rights reserved.
  5 * 
  6 * The contents of this file are subject to the terms of the Common Development
  7 * and Distribution License (the "License"). You may not use this file except
  8 * in compliance with the License.
  9 * 
 10 * You can obtain a copy of the license at http://www.sun.com/cddl/cddl.html.
 11 * See the License for the specific language governing permissions and limitations
 12 * under the License.
 13 */
 14
 15package org.openesb.components.rules4jbi.engine.component;
 16
 17import java.io.File;
 18import java.util.concurrent.Callable;
 19import java.util.concurrent.CompletionService;
 20import java.util.concurrent.ExecutionException;
 21import java.util.concurrent.ExecutorService;
 22import java.util.concurrent.Executors;
 23import java.util.concurrent.Future;
 24import java.util.concurrent.TimeUnit;
 25
 26import javax.jbi.JBIException;
 27import javax.jbi.component.Component;
 28import javax.jbi.component.ComponentContext;
 29import javax.jbi.component.ComponentLifeCycle;
 30import javax.jbi.component.ServiceUnitManager;
 31import javax.jbi.messaging.ExchangeStatus;
 32import javax.jbi.messaging.InOut;
 33import javax.jbi.messaging.MessageExchange;
 34import javax.jbi.servicedesc.ServiceEndpoint;
 35import javax.management.ObjectName;
 36
 37import org.w3c.dom.Document;
 38import org.w3c.dom.DocumentFragment;
 39
 40import com.google.inject.Guice;
 41import com.google.inject.Inject;
 42import com.google.inject.Injector;
 43import com.google.inject.Stage;
 44
 45import net.jcip.annotations.NotThreadSafe;
 46
 47import org.openesb.components.rules4jbi.shared.logging.Logger;
 48
 49import org.openesb.components.rules4jbi.engine.guice.annotations.Main;
 50import org.openesb.components.rules4jbi.engine.guice.annotations.MessageExchangeProcessor;
 51import org.openesb.components.rules4jbi.engine.guice.modules.ConstantModule;
 52import org.openesb.components.rules4jbi.engine.guice.modules.ExecutorModule;
 53import org.openesb.components.rules4jbi.engine.guice.modules.JBIModule;
 54import org.openesb.components.rules4jbi.engine.guice.modules.LoggerModule;
 55import org.openesb.components.rules4jbi.engine.util.DOMUtils;
 56
 57import static org.openesb.components.rules4jbi.engine.util.ConcurrencyUtils.shutdownExecutorService;
 58
 59/**
 60 * This class is the entry point of the Rules service engine to the JBI runtime.
 61 * It implements both the <code>javax.jbi.component.Component</code> and
 62 * <code>javax.jbi.component.ComponentLifeCycle</code> interfaces.
 63 *
 64 * @author Milan Fort (http://www.milanfort.com/)
 65 * @version $Revision: 1.2 $ $Date: 2008/07/14 16:30:26 $
 66 * 
 67 * @see javax.jbi.component.Component
 68 * @see javax.jbi.component.ComponentLifeCycle
 69 * @since 0.1
 70 */
 71@NotThreadSafe
 72public class Rules4JBIComponent implements Component, ComponentLifeCycle {
 73    
 74    /** Time to wait for tasks to complete after component was stopped; in seconds. */
 75    private static final long TASK_COMPLETION_WAIT_TIME = 2;
 76    
 77    @Inject @Main
 78    private Logger logger;
 79    
 80    @Inject
 81    private Injector injector;
 82
 83    @Inject
 84    private Rules4JBIServiceUnitManager manager;
 85    
 86    @Inject
 87    private DeliveryChannelService deliveryChannelService;
 88    
 89    @Inject
 90    private ComponentContext componentContext;
 91    
 92    @Inject @Main
 93    private ExecutorService mainExecutorService;
 94
 95    /**
 96     * This completition service uses mainExecutorService as its internal executor.
 97     * 
 98     * @see #mainExecutorService
 99     */
100    @Inject @MessageExchangeProcessor
101    private CompletionService<InOut> messageExchangeProcessor;
102    
103    private ExecutorService dispatcher;
104
105    private ExecutorService collector;
106
107    
108    /* ComponentLifeCycle Methods */
109    
110    public ObjectName getExtensionMBeanName() {
111        logger.entering(this.getClass(), "getExtensionMBeanName");
112        
113        return null;
114    }
115    
116    public void init(ComponentContext componentContext) throws JBIException {
117        if (componentContext == null) {
118            throw new JBIException("Null component context received during bootstrap");
119        }
120
121        /*
122         * The JBI spec doesn't guarantee that the same instance will be provided
123         * during the lifecycle of the component. Therefore, we need to re-inject
124         * the dependencie upon every init() method call.
125         */
126//      if (this.componentContext != null && this.componentContext != componentContext) {
127//          throw new JBIException("Different instance of component context during lifecycle is not supported");
128//      }
129
130        boolean configurationValuesLoaded = true;
131        InstallationConfiguration configuration = null;
132        
133        try { 
134            configuration = InstallationConfiguration.load(
135                    new File(componentContext.getWorkspaceRoot(), InstallationConfiguration.CONFIG_FILE_NAME));
136            
137        } catch (InvalidInstallationConfigurationException e) {
138            
139            configurationValuesLoaded = false;
140            configuration = new InstallationConfiguration();
141        }
142        
143        injector = Guice.createInjector(Stage.PRODUCTION,
144                new JBIModule(componentContext),
145                new LoggerModule(componentContext),
146                new ConstantModule(configuration.getMaxServiceUnits()),
147                new ExecutorModule(configuration.getPoolSize()));
148        
149        injector.injectMembers(this);
150        manager.injectDependenciesIntoServiceUnits();
151        
152        if (logger == null) {
153            throw new JBIException("Unable to properly inject depencencies");
154        }
155
156        logger.entering(this.getClass(), "init");
157        
158        logger.info("Initializing component '%s'", componentContext.getComponentName());
159
160        if (!configurationValuesLoaded) {
161            logger.warning("Failed to load configuration file; using default values");
162        }
163        
164        logger.config("Thread pool size: %d", configuration.getPoolSize());
165        logger.config("Maximum allowed service units: %d", configuration.getMaxServiceUnits());
166        
167        deliveryChannelService.init();
168        
169        dispatcher = Executors.newSingleThreadExecutor();
170        
171        collector = Executors.newSingleThreadExecutor();
172        
173        logger.exiting(this.getClass(), "init");
174    }
175
176    public void start() throws JBIException {
177        logger.entering(this.getClass(), "start");
178        
179        deliveryChannelService.start();
180        
181        collector.execute(new CollectorTask());
182        dispatcher.execute(new DispatcherTask());
183        
184        /*
185         * JBI runtime will start the service units automatically, if appropriate
186         */
187    }
188
189    public void stop() throws JBIException {
190        logger.entering(this.getClass(), "stop");
191        
192        deliveryChannelService.stop();
193        
194        /*
195         * JBI runtime will stop the service units automatically, if appropriate
196         */
197    }
198    
199    public void shutDown() throws JBIException {
200        logger.entering(this.getClass(), "shutDown");
201        
202        shutdownExecutorService(logger, "Dispatcher", dispatcher);
203        
204        shutdownExecutorService(logger, "Collector", collector);
205        
206        shutdownExecutorService(logger, "Main Executor", mainExecutorService);
207        
208        deliveryChannelService.shutDown();
209    }
210
211    
212    /* Component Methods */
213    
214    public ComponentLifeCycle getLifeCycle() {
215        return this;
216    }
217    
218    public Document getServiceDescription(ServiceEndpoint endpoint) {
219        logger.entering(this.getClass(), "getServiceDescription", endpoint);
220
221        ServiceUnit serviceUnit = manager.findByServiceEndpoint(endpoint);
222        
223        return serviceUnit != null ? serviceUnit.getServiceDescription() : null;
224    }
225
226    public ServiceUnitManager getServiceUnitManager() {
227        logger.entering(this.getClass(), "getServiceUnitManager");
228
229        return manager;
230    }
231
232    public boolean isExchangeWithConsumerOkay(ServiceEndpoint endpoint, MessageExchange exchange) {
233        logger.entering(this.getClass(), "isExchangeWithConsumerOkay");
234        
235        /*
236         * TODO: We should check whether we want/are able to handle this exchange
237         */  
238        
239        return true;
240    }
241
242    public boolean isExchangeWithProviderOkay(ServiceEndpoint endpoint, MessageExchange exchange) {
243        logger.entering(this.getClass(), "isExchangeWithProviderOkay");
244        
245        /*
246         * TODO: We should probably return false here. We do not initiate message exchanges,
247         * so this method should never be called on us.
248         */  
249        
250        return true;
251    }
252    
253    public ServiceEndpoint resolveEndpointReference(DocumentFragment epr) {
254        logger.entering(this.getClass(), "resolveEndpointReference", DOMUtils.documentFragmentToString(epr));
255
256        /* We do not support dynamic endpoints */
257        return null;
258    }
259
260    
261    /* Tasks */
262    
263    /**
264     * Task responsible for retrieving received <code>MessageExchange</code>s
265     * and dispatching them to the appropriate service unit for processing.
266     */
267    private class DispatcherTask implements Runnable {
268
269        public void run() {
270            logger.fine("Starting message dispatcher");
271            
272            while (true) {
273                try {
274                    MessageExchange messageExchange = deliveryChannelService.receive();
275
276                    if (messageExchange instanceof EmptyMessageExchange) {
277                        logger.fine("Message dispatcher received terminal message");
278
279                        messageExchangeProcessor.submit(new Callable<InOut>() {
280
281                            public InOut call() throws Exception {
282
283                                /* give the other tasks some time to complete */
284                                TimeUnit.SECONDS.sleep(TASK_COMPLETION_WAIT_TIME);
285
286                                return new EmptyMessageExchange();
287                            }
288                        });
289
290                        break;
291
292                    } else if (messageExchange instanceof InOut) {
293                        InOut inOut = (InOut) messageExchange;
294
295                        if (ExchangeStatus.ACTIVE.equals(inOut.getStatus())) {
296
297                            logger.fine("Searching for service unit for the endpoint: %s", inOut.getEndpoint());
298                            ServiceUnit serviceUnit = manager.findByServiceEndpoint(inOut.getEndpoint());
299
300                            if (serviceUnit != null) {
301                                serviceUnit.process(inOut);
302                                
303                            } else {
304                                logger.warning("Could not find providing service unit");
305                            }
306                            
307                        } else if (ExchangeStatus.DONE.equals(inOut.getStatus())) {
308                            logger.fine("Received message with DONE status");
309                            
310                        } else if (ExchangeStatus.ERROR.equals(inOut.getStatus())) {
311                            logger.warning("Received message with ERROR status", inOut.getError());
312                        }
313                        
314                    } else {
315                        logger.severe("Received incorrect MEP");
316                    }
317
318                } catch (InterruptedException e) {
319                    logger.fine("Message dispatcher interrupted");
320                    
321                    break;
322                }
323            }
324            
325            logger.fine("Message dispatcher terminated");
326        }
327    }
328
329    /**
330     * Task responsible for retrieving completed <code>MessageExchange</code>s
331     * and sending them back to the caller via <code>DeliveryChannelService</code>.
332     */
333    private class CollectorTask implements Runnable {
334
335        public void run() {
336            logger.fine("Starting results collector");
337
338            while (true) {
339                try {
340                    Future<InOut> processedMessageExchange = messageExchangeProcessor.take();
341
342                    InOut processedMessage = processedMessageExchange.get();
343
344                    deliveryChannelService.send(processedMessage);
345                    
346                    if (processedMessage instanceof EmptyMessageExchange) {
347                        logger.fine("Results collector received terminal message");
348                        
349                        break;
350                    }
351
352                } catch (InterruptedException e) {
353                    logger.fine("Results collector interrupted");
354                    
355                    break;
356
357                } catch (ExecutionException e) {
358                    logger.warning("Error while executing task", e);
359                }
360            }
361            
362            logger.fine("Results collector terminated");
363        }
364    }
365}