/* * Copyright 2013 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.kie.aries.blueprint.namespace; import org.apache.aries.blueprint.BeanProcessor; import org.apache.aries.blueprint.ParserContext; import org.apache.aries.blueprint.PassThroughMetadata; import org.apache.aries.blueprint.mutable.MutableBeanArgument; import org.apache.aries.blueprint.mutable.MutablePassThroughMetadata; import org.drools.compiler.kie.builder.impl.ClasspathKieProject; import org.drools.compiler.kie.builder.impl.InternalKieModule; import org.drools.compiler.kie.builder.impl.KieBuilderImpl; import org.drools.compiler.kie.builder.impl.KieRepositoryImpl; import org.drools.compiler.kproject.ReleaseIdImpl; import org.drools.compiler.kproject.models.KieBaseModelImpl; import org.drools.compiler.kproject.models.KieModuleModelImpl; import org.drools.compiler.kproject.models.KieSessionModelImpl; import org.kie.api.KieServices; import org.kie.api.builder.ReleaseId; import org.kie.api.builder.model.KieModuleModel; import org.kie.api.builder.model.KieSessionModel; import org.kie.api.conf.DeclarativeAgendaOption; import org.kie.api.conf.EqualityBehaviorOption; import org.kie.api.conf.EventProcessingOption; import org.kie.api.runtime.conf.ClockTypeOption; import org.kie.aries.blueprint.factorybeans.Initializable; import org.kie.aries.blueprint.factorybeans.KBaseOptions; import org.kie.aries.blueprint.factorybeans.KSessionOptions; import org.kie.aries.blueprint.factorybeans.KieObjectsFactoryBean; import org.osgi.framework.Bundle; import org.osgi.framework.FrameworkUtil; import org.osgi.service.blueprint.container.BlueprintContainer; import org.osgi.service.blueprint.reflect.BeanArgument; import org.osgi.service.blueprint.reflect.BeanMetadata; import org.osgi.service.blueprint.reflect.ComponentMetadata; import org.osgi.service.blueprint.reflect.ValueMetadata; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.Method; import java.net.URL; import java.util.List; import java.util.Map; import java.util.Set; public class KieObjectsInjector implements BeanProcessor { private static final Logger log = LoggerFactory.getLogger(KieObjectsInjector.class); private BlueprintContainer blueprintContainer; private String contextId; private String configFilePath; private ReleaseId releaseId; private URL configFileURL; private ParserContext parserContext; private BlueprintContextHelper context; /** The list of Aries Blueprint XML files*/ protected java.util.List<java.net.URL> resources; public KieObjectsInjector(List<URL> resources) { this.resources = resources; } public KieObjectsInjector(String contextId) { this.contextId = contextId; } public KieObjectsInjector(String contextId, ParserContext parserContext) { this.contextId = contextId; this.parserContext = parserContext; } public KieObjectsInjector(List<URL> resources, String contextId) { this.resources = resources; this.contextId = contextId; } public KieObjectsInjector() { } public void setBlueprintContainer(BlueprintContainer blueprintContainer) { this.blueprintContainer = blueprintContainer; this.context = new BlueprintContextHelper( blueprintContainer ); } public void afterKmoduleSet() { log.debug(" :: Starting Blueprint KieObjectsInjector for kmodule ("+contextId+") :: "); if ( resources == null || resources.isEmpty()) { configFileURL = getClass().getResource("/"); if (configFileURL == null) { createOsgiKieModule(); return; } configFilePath = configFileURL.getPath(); } else { configFileURL = resources.get(0); configFilePath = configFileURL.getPath(); log.debug(" :: Trying to intialize the KieModule from " + configFileURL + " :: "); } if ( configFilePath == null) { throw new RuntimeException("Failure creating a KieModule. Unable to determine the Configuration File Path."); } String pomProperties = ClasspathKieProject.getPomProperties(configFilePath); releaseId = ReleaseIdImpl.fromPropertiesString(pomProperties); KieModuleModel kieModuleModel = getKieModuleModel(); injectKieModule(kieModuleModel); addKieModuleToRepo(kieModuleModel); log.debug(" :: Completed Injecting KieObjects from the Blueprint Bean Processor ("+contextId+") :: "); } protected void injectKieModule(KieModuleModel kieModuleModel) { ComponentMetadata componentMetadata = blueprintContainer.getComponentMetadata(contextId); if ( componentMetadata instanceof MutablePassThroughMetadata){ ((MutablePassThroughMetadata)componentMetadata).setObject(kieModuleModel); } } public void afterImportSet() { // no-op } private void createOsgiKieModule() { configFileURL = getConfigFileURL(); if (releaseId == null) { releaseId = KieRepositoryImpl.INSTANCE.getDefaultReleaseId(); } KieModuleModel kieModuleModel = getKieModuleModel(); KieBuilderImpl.setDefaultsforEmptyKieModule(kieModuleModel); injectKieModule(kieModuleModel); InternalKieModule internalKieModule = createOsgiKModule(kieModuleModel); if ( internalKieModule != null ) { KieServices ks = KieServices.Factory.get(); ks.getRepository().addKieModule(internalKieModule); log.info(" :: Added KieModule From KieObjectsInjector ::"); } } private URL getConfigFileURL() { try { Method m = Class.forName(blueprintContainer.getClass().getName(), true, blueprintContainer.getClass().getClassLoader()) .getMethod("getBundle"); Bundle bundle = (Bundle)m.invoke(blueprintContainer); return bundle.getEntry("/"); } catch (Exception e) { } return FrameworkUtil.getBundle(this.getClass()).getEntry("/"); } private InternalKieModule createOsgiKModule(KieModuleModel kieProject) { Method m; try { Class<?> c = Class.forName(ClasspathKieProject.OSGI_KIE_MODULE_CLASS_NAME, true, KieBuilderImpl.class.getClassLoader()); m = c.getMethod("create", URL.class, ReleaseId.class, KieModuleModel.class); } catch (Exception e) { throw new RuntimeException("It is necessary to have the drools-osgi-integration module on the path in order to create a KieProject from an osgi bundle", e); } try { return (InternalKieModule) m.invoke(null, configFileURL, releaseId, kieProject); } catch (Exception e) { throw new RuntimeException("Failure creating a OsgiKieModule caused by: " + e.getMessage(), e); } } protected void addKieModuleToRepo(KieModuleModel kieModuleModel) { String rootPath = configFilePath; if ( rootPath.lastIndexOf( ':' ) >= 2 ) { // avoid to trucate Windows paths like C:\my\folder\... rootPath = configFilePath.substring( rootPath.lastIndexOf( ':' ) + 1 ); } KieBuilderImpl.setDefaultsforEmptyKieModule(kieModuleModel); InternalKieModule internalKieModule = ClasspathKieProject.createInternalKieModule(kieModuleModel, releaseId, rootPath); if ( internalKieModule != null ) { KieServices ks = KieServices.Factory.get(); ks.getRepository().addKieModule(internalKieModule); log.info(" :: Added KieModule From KieObjectsInjector ::"); } } protected KieModuleModel getKieModuleModel() { KieModuleModelImpl kieModuleModel = new KieModuleModelImpl(); Set<String> ids = blueprintContainer.getComponentIds(); for (String id: ids) { ComponentMetadata componentMetadata = blueprintContainer.getComponentMetadata(id); if ( componentMetadata instanceof BeanMetadata) { BeanMetadata metadata = (BeanMetadata)componentMetadata; if (KieObjectsFactoryBean.class.getName().equals(metadata.getClassName())) { if ("fetchKBase".equalsIgnoreCase(metadata.getFactoryMethod())) { BeanArgument kbRefArg = metadata.getArguments().get(0); String kBaseName = ((ValueMetadata) kbRefArg.getValue()).getStringValue(); KieBaseModelImpl kBase = new KieBaseModelImpl(); kBase.setKModule(kieModuleModel); kBase.setName(kBaseName); BeanArgument kbOptionsArg = metadata.getArguments().get(2); PassThroughMetadata passThroughMetadata = (PassThroughMetadata) kbOptionsArg.getValue(); KBaseOptions kBaseOptions = (KBaseOptions) passThroughMetadata.getObject(); String packages = kBaseOptions.getPackages(); if ( !kBaseOptions.getPackages().isEmpty()) { for ( String pkg : packages.split( "," ) ) { kBase.addPackage( pkg.trim() ); } } String includes = kBaseOptions.getIncludes(); if ( !includes.isEmpty() ) { for ( String include : includes.split( "," ) ) { kBase.addInclude( include.trim() ); } } String equalsBehavior = kBaseOptions.getEqualsBehavior(); if ( !equalsBehavior.isEmpty() ) { kBase.setEqualsBehavior( EqualityBehaviorOption.determineEqualityBehavior(equalsBehavior) ); } String eventProcessingMode = kBaseOptions.getEventProcessingMode(); if ( !eventProcessingMode.isEmpty() ) { kBase.setEventProcessingMode( EventProcessingOption.determineEventProcessingMode(eventProcessingMode) ); } String declarativeAgenda = kBaseOptions.getDeclarativeAgenda(); if ( !declarativeAgenda.isEmpty() ) { kBase.setDeclarativeAgenda( DeclarativeAgendaOption.determineDeclarativeAgenda(declarativeAgenda) ); } kieModuleModel.getRawKieBaseModels().put(kBase.getName(), kBase); MutablePassThroughMetadata throughMetadata = parserContext.createMetadata(MutablePassThroughMetadata.class); throughMetadata.setObject(releaseId); ((MutableBeanArgument)metadata.getArguments().get(1)).setValue(throughMetadata); addKieSessionModels(kBase); } } } } return kieModuleModel; } private void addKieSessionModels(KieBaseModelImpl kieBaseModel) { Set<String> ids = blueprintContainer.getComponentIds(); for (String id: ids) { ComponentMetadata componentMetadata = blueprintContainer.getComponentMetadata(id); if ( componentMetadata instanceof BeanMetadata) { BeanMetadata metadata = (BeanMetadata)componentMetadata; if (KieObjectsFactoryBean.class.getName().equals(metadata.getClassName())) { if ("createKieSession".equalsIgnoreCase(metadata.getFactoryMethod())){ BeanArgument beanArgument = metadata.getArguments().get(0); String ksessionName = ((ValueMetadata)beanArgument.getValue()).getStringValue(); BeanArgument kbOptionsArg = metadata.getArguments().get(5); PassThroughMetadata passThroughMetadata = (PassThroughMetadata) kbOptionsArg.getValue(); KSessionOptions kSessionOptions = (KSessionOptions) passThroughMetadata.getObject(); String type = kSessionOptions.getType(); String kbaseRef = kSessionOptions.getkBaseRef(); if( kbaseRef.equalsIgnoreCase(kieBaseModel.getName())) { KieSessionModelImpl kSession = new KieSessionModelImpl(kieBaseModel, ksessionName); kSession.setType(type != null ? KieSessionModel.KieSessionType.valueOf(type.toUpperCase()) : KieSessionModel.KieSessionType.STATEFUL); kSession.setDefault( "true".equals( kSessionOptions.getDef() ) ); String clockType = kSessionOptions.getClockType(); if ( clockType != null && !clockType.isEmpty() ) { kSession.setClockType( ClockTypeOption.get(clockType) ); } String scope = kSessionOptions.getScope(); if ( scope !=null && !scope.isEmpty() ) { kSession.setScope( scope.trim() ); } Map<String, KieSessionModel> rawKieSessionModels = kieBaseModel.getRawKieSessionModels(); rawKieSessionModels.put(kSession.getName(), kSession); MutablePassThroughMetadata throughMetadata = parserContext.createMetadata(MutablePassThroughMetadata.class); throughMetadata.setObject(releaseId); ((MutableBeanArgument)metadata.getArguments().get(1)).setValue(throughMetadata); } } } } } } @Override public Object beforeInit(Object o, String s, BeanCreator beanCreator, BeanMetadata beanMetadata) { return o; } @Override public Object afterInit(Object o, String s, BeanCreator beanCreator, BeanMetadata beanMetadata) { try { return o instanceof Initializable ? ( (Initializable) o ).init( context ) : o; } catch (Exception e) { throw new RuntimeException( e ); } } @Override public void beforeDestroy(Object o, String s) { } @Override public void afterDestroy(Object o, String s) { } }