/* * Copyright 2010 Red Hat, Inc. and/or its affiliates. * * 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.compiler.osgi; import java.util.Dictionary; import java.util.Hashtable; import java.util.concurrent.Callable; import java.util.function.BiConsumer; import org.drools.compiler.builder.impl.KnowledgeBuilderFactoryServiceImpl; import org.drools.compiler.compiler.BPMN2ProcessProvider; import org.drools.compiler.compiler.DecisionTableProvider; import org.drools.core.marshalling.impl.ProcessMarshallerFactoryService; import org.drools.core.runtime.process.ProcessRuntimeFactoryService; import org.kie.api.Service; import org.kie.api.builder.KieScannerFactoryService; import org.kie.internal.assembler.KieAssemblerService; import org.kie.internal.assembler.KieAssemblers; import org.kie.internal.builder.KnowledgeBuilderFactoryService; import org.kie.internal.runtime.KieRuntimeService; import org.kie.internal.runtime.KieRuntimes; import org.kie.internal.utils.ClassLoaderResolver; import org.kie.internal.utils.ServiceRegistry; import org.kie.internal.utils.ServiceRegistryImpl; import org.kie.internal.weaver.KieWeaverService; import org.kie.internal.weaver.KieWeavers; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import org.osgi.util.tracker.ServiceTracker; import org.osgi.util.tracker.ServiceTrackerCustomizer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Activator implements BundleActivator { protected static final transient Logger logger = LoggerFactory.getLogger(Activator.class); private ServiceRegistration kbuilderReg; private ServiceTracker dtableTracker; private ServiceTracker bpmn2Tracker; private ServiceTracker processRuntimeTracker; private ServiceTracker processMarshallerTracker; private ServiceTracker scannerTracker; private ServiceTracker classResolverTracker; private ServiceTracker kieAssemblerServiceTracker; private ServiceTracker kieWeaverServiceTracker; private ServiceTracker kieRuntimeServiceTracker; public void start(BundleContext bc) throws Exception { logger.info( "registering compiler services" ); this.kbuilderReg = bc.registerService( new String[]{KnowledgeBuilderFactoryService.class.getName(), Service.class.getName()}, new KnowledgeBuilderFactoryServiceImpl(), new Hashtable() ); this.dtableTracker = new ServiceTracker( bc, bc.createFilter( "(|(" + Constants.OBJECTCLASS + "=" + DecisionTableProvider.class.getName() + ")(" + Constants.OBJECTCLASS + "=" + BPMN2ProcessProvider.class.getName() +") )"), new DroolsServiceTracker( bc, this ) ); this.dtableTracker.open(); this.bpmn2Tracker = new ServiceTracker( bc, BPMN2ProcessProvider.class.getName(), new DroolsServiceTracker( bc, this ) ); this.bpmn2Tracker.open(); this.processRuntimeTracker = new ServiceTracker( bc, ProcessRuntimeFactoryService.class.getName(), new DroolsServiceTracker( bc, this ) ); this.processRuntimeTracker.open(); this.processMarshallerTracker = new ServiceTracker( bc, ProcessMarshallerFactoryService.class.getName(), new DroolsServiceTracker( bc, this ) ); this.processRuntimeTracker.open(); this.scannerTracker = new ServiceTracker( bc, KieScannerFactoryService.class.getName(), new DroolsServiceTracker( bc, this ) ); this.scannerTracker.open(); this.classResolverTracker = new ServiceTracker( bc, ClassLoaderResolver.class.getName(), new DroolsServiceTracker( bc, this ) ); this.classResolverTracker.open(); this.kieAssemblerServiceTracker = new ServiceTracker( bc, KieAssemblerService.class.getName(), new DroolsKieComponentServiceTracker<KieAssemblerService>( bc, Activator::registerKieAssembler ) ); this.kieAssemblerServiceTracker.open(); this.kieWeaverServiceTracker = new ServiceTracker( bc, KieWeaverService.class.getName(), new DroolsKieComponentServiceTracker<KieWeaverService>( bc, Activator::registerKieWeaver ) ); this.kieWeaverServiceTracker.open(); this.kieRuntimeServiceTracker = new ServiceTracker( bc, KieRuntimeService.class.getName(), new DroolsKieComponentServiceTracker<KieRuntimeService>( bc, Activator::registerKieRuntime ) ); this.kieRuntimeServiceTracker.open(); logger.info( "compiler services registered" ); } public void stop(BundleContext bc) throws Exception { this.kbuilderReg.unregister(); this.dtableTracker.close(); this.bpmn2Tracker.close(); this.processRuntimeTracker.close(); this.processMarshallerTracker.close(); this.scannerTracker.close(); this.classResolverTracker.close(); this.kieAssemblerServiceTracker.close(); this.kieWeaverServiceTracker.close(); this.kieRuntimeServiceTracker.close(); } private static void registerKieAssembler(ServiceRegistry registry, KieAssemblerService service) { registry.get( KieAssemblers.class ).getAssemblers().put( service.getResourceType(), service ); } private static void registerKieWeaver(ServiceRegistry registry, KieWeaverService service) { registry.get(KieWeavers.class).getWeavers().put(service.getResourceType(), service); } private static void registerKieRuntime(ServiceRegistry registry, KieRuntimeService service) { registry.get(KieRuntimes.class).getRuntimes().put(service.getServiceInterface().getName(), service); } public static class DroolsKieComponentServiceTracker<T> implements ServiceTrackerCustomizer { private final BundleContext bc; private final BiConsumer<ServiceRegistry, T> register; public DroolsKieComponentServiceTracker( BundleContext bc, BiConsumer<ServiceRegistry, T> register ) { this.bc = bc; this.register = register; } public Object addingService(ServiceReference ref) { T service = (T) this.bc.getService( ref ); logger.info( "registering : " + service + " : " + service.getClass().getInterfaces()[0] ); register.accept( ServiceRegistryImpl.getInstance(), service ); return service; } public void modifiedService(ServiceReference arg0, Object arg1) { } public void removedService(ServiceReference ref, Object arg1) { } } public static class DroolsServiceTracker implements ServiceTrackerCustomizer { private final BundleContext bc; private final Activator activator; private final Class serviceClass; public DroolsServiceTracker(BundleContext bc, Activator activator) { this(bc, activator, null); } public DroolsServiceTracker(BundleContext bc, Activator activator, Class serviceClass) { this.bc = bc; this.activator = activator; this.serviceClass = serviceClass; } public Object addingService(ServiceReference ref) { Service service = (Service) this.bc.getService( ref ); logger.info( "registering compiler : " + service + " : " + service.getClass().getInterfaces()[0] ); Dictionary dic = new Hashtable(); ServiceReference regServiceRef = this.activator.kbuilderReg.getReference(); for ( String key : regServiceRef.getPropertyKeys() ) { dic.put( key, regServiceRef.getProperty( key ) ); } dic.put( service.getClass().getInterfaces()[0].getName(), "true" ); activator.kbuilderReg.setProperties( dic ); ServiceRegistryImpl.getInstance().registerLocator( serviceClass != null ? serviceClass : service.getClass().getInterfaces()[0], new BundleContextInstantiator( this.bc, ref ) ); return service; } public void modifiedService(ServiceReference arg0, Object arg1) { } public void removedService(ServiceReference ref, Object arg1) { Service service = (Service) bc.getService( ref ); ServiceRegistryImpl.getInstance().unregisterLocator( service.getClass().getInterfaces()[0] ); logger.info( "unregistering compiler : " + service + " : " + service.getClass().getInterfaces()[0] ); } } public static class BundleContextInstantiator<V> implements Callable<V> { private BundleContext bc; private ServiceReference ref; public BundleContextInstantiator(BundleContext bc, ServiceReference ref) { this.bc = bc; this.ref = ref; } public V call() throws Exception { return (V) this.bc.getService(this.ref); } } }