/*
* 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.kie.internal.utils;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicReference;
import org.kie.api.KieServices;
import org.kie.api.Service;
import org.kie.api.builder.KieScannerFactoryService;
import org.kie.api.concurrent.KieExecutors;
import org.kie.api.io.KieResources;
import org.kie.api.marshalling.KieMarshallers;
import org.kie.api.persistence.jpa.KieStoreServices;
import org.kie.internal.assembler.KieAssemblers;
import org.kie.internal.assembler.KieAssemblersImpl;
import org.kie.internal.process.CorrelationKeyFactory;
import org.kie.internal.runtime.KieRuntimes;
import org.kie.internal.runtime.KieRuntimesImpl;
import org.kie.internal.runtime.beliefs.KieBeliefs;
import org.kie.internal.runtime.beliefs.KieBeliefsImpl;
import org.kie.internal.weaver.KieWeavers;
import org.kie.internal.weaver.KieWeaversImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This is an internal class, not for public consumption.
*/
public class ServiceRegistryImpl
implements
ServiceRegistry {
public final String fileName = "kie.conf";
public final String path = "META-INF/" + fileName;
private static final ServiceRegistry instance = new ServiceRegistryImpl();
protected static final transient Logger logger = LoggerFactory.getLogger( ServiceRegistryImpl.class );
private final Map<String, Callable< ? >> registry = new HashMap<String, Callable< ? >>();
private final Map<String, Callable< ? >> defaultServices = new HashMap<String, Callable< ? >>();
public static ServiceRegistry getInstance() {
return instance;
}
public ServiceRegistryImpl() {
init();
}
/* (non-Javadoc)
* @see org.kie.util.internal.ServiceRegistry#registerLocator(java.lang.String, java.util.concurrent.Callable)
*/
public synchronized void registerLocator(Class cls,
Callable cal) {
this.registry.put( cls.getName(),
cal );
}
/* (non-Javadoc)
* @see org.kie.util.internal.ServiceRegistry#unregisterLocator(java.lang.String)
*/
public synchronized void unregisterLocator(Class cls) {
this.registry.remove( cls.getName() );
}
synchronized void registerInstance(Service service,
Map map) {
//this.context.getProperties().put( "org.dr, value )
logger.info( "regInstance : " + map );
String[] values = (String[]) map.get( "objectClass" );
for ( String v : values ) {
logger.info( v );
}
// logger.info( "register : " + service );
this.registry.put( service.getClass().getInterfaces()[0].getName(),
new ReturnInstance<Service>( service ) );
}
/* (non-Javadoc)
* @see org.kie.util.internal.ServiceRegistry#unregisterLocator(java.lang.String)
*/
synchronized void unregisterInstance(Service service,
Map map) {
logger.info( "unregister : " + map );
String name = service.getClass().getInterfaces()[0].getName();
this.registry.remove( name );
this.registry.put( name,
this.defaultServices.get( name ) );
}
public synchronized <T> T get(Class<T> cls) {
Callable< ? > cal = this.registry.get( cls.getName() );
if ( cal != null ) {
try {
return cls.cast( cal.call() );
} catch ( Exception e ) {
throw new IllegalArgumentException( "Unable to instantiate service for Class '" + (cls != null ? cls.getName() : null) + "'",
e );
}
} else {
cal = this.defaultServices.get( cls.getName() );
try {
return cls.cast( cal.call() );
} catch ( Exception e ) {
throw new IllegalArgumentException( "Unable to instantiate service for Class '" + (cls != null ? cls.getName() : null) + "'",
e );
}
}
}
private void init() {
addDefault( "org.kie.internal.builder.KnowledgeBuilderFactoryService",
"org.drools.compiler.builder.impl.KnowledgeBuilderFactoryServiceImpl" );
addDefault( "org.kie.api.builder.KnowledgeContainerFactoryService",
"org.drools.core.builder.impl.KnowledgeContainerFactoryServiceImpl" );
addDefault( "org.kie.internal.KnowledgeBaseFactoryService",
"org.drools.core.impl.KnowledgeBaseFactoryServiceImpl" );
addDefault( KieResources.class,
"org.drools.core.io.impl.ResourceFactoryServiceImpl" );
addDefault( KieMarshallers.class,
"org.drools.core.marshalling.impl.MarshallerProviderImpl");
addDefault( KieExecutors.class,
"org.drools.core.concurrent.ExecutorProviderImpl");
addDefault( KieServices.class,
"org.drools.compiler.kie.builder.impl.KieServicesImpl");
addDefaultFactory( KieScannerFactoryService.class,
"org.kie.scanner.KieScannerFactoryServiceImpl");
addDefault( KieStoreServices.class,
"org.drools.persistence.jpa.KnowledgeStoreServiceImpl");
addDefault( CorrelationKeyFactory.class,
"org.jbpm.persistence.correlation.JPACorrelationKeyFactory");
addDefault( ClassLoaderResolver.class,
"org.kie.scanner.MavenClassLoaderResolver" );
addDefault( ServiceDiscovery.class,
"org.drools.core.util.ServiceDiscoveryImpl" );
defaultServices.put( KieAssemblers.class.getName(),
new ReturnInstance( new KieAssemblersImpl()) );
defaultServices.put( KieWeavers.class.getName(),
new ReturnInstance( new KieWeaversImpl()) );
defaultServices.put( KieRuntimes.class.getName(),
new ReturnInstance( new KieRuntimesImpl()) );
defaultServices.put( KieBeliefs.class.getName(),
new ReturnInstance( new KieBeliefsImpl()) );
initServiceDiscovery();
}
private void initServiceDiscovery() {
Enumeration<URL> confResources = null;
try {
confResources = getClassLoader().getResources( path );
} catch ( Exception e ) {
// no conf file or no ServiceDiscovery - ignore
}
if (confResources != null && confResources.hasMoreElements()) {
get( ServiceDiscovery.class ).discoverFactories( confResources, this );
}
}
public synchronized void addDefault(Class cls,
String impl) {
addDefault(cls.getName(), impl);
}
private synchronized void addDefault(String service,
String impl) {
ReflectionInstantiator<Service> resourceRi = new ReflectionInstantiator<Service>( impl );
defaultServices.put( service,
resourceRi );
}
public synchronized void addDefaultFactory(Class cls,
String impl) {
addDefaultFactory(cls.getName(), impl);
}
private synchronized void addDefaultFactory(String service,
String impl) {
FactoryInstantiator<Service> resourceRi = new FactoryInstantiator<Service>( impl );
defaultServices.put(service,
resourceRi);
}
public static class ReflectionInstantiator<V>
implements
Callable<V> {
private final String name;
public ReflectionInstantiator(String name) {
this.name = name;
}
public V call() throws Exception {
return (V) newInstance( name );
}
static <T> T newInstance(String name) {
try {
Class<T> cls = (Class<T>) Class.forName( name );
return cls.newInstance();
} catch ( Exception e2 ) {
throw new IllegalArgumentException( "Unable to instantiate '" + name + "'",
e2 );
}
}
}
public static class FactoryInstantiator<V>
implements
Callable<V> {
private final String name;
private final AtomicReference<V> service = new AtomicReference<V>();
public FactoryInstantiator(String name) {
this.name = name;
}
public V call() throws Exception {
if (service.get() == null) {
try {
Class<V> cls = (Class<V>) Class.forName( name );
service.compareAndSet(null, cls.newInstance());
} catch ( Exception e ) {
throw new IllegalArgumentException( "Unable to instantiate '" + name + "'",
e );
}
}
return service.get();
}
}
public static class ReturnInstance<V>
implements
Callable<V> {
private final Service service;
public ReturnInstance(Service service) {
this.service = service;
}
public V call() throws Exception {
return (V) service;
}
}
private static ClassLoader getClassLoader() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if (cl == null) {
cl = ClassLoader.getSystemClassLoader();
}
if (cl == null) {
cl = ClassLoaderUtil.class.getClassLoader();
}
return cl;
}
}