/*
* Copyright 2015 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.
*
* 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.jbpm.runtime.manager.impl.deploy;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManagerFactory;
import org.kie.api.KieServices;
import org.kie.api.runtime.manager.RuntimeManager;
import org.kie.api.task.TaskService;
import org.kie.api.executor.ExecutorService;
import org.kie.internal.runtime.Cacheable;
import org.kie.internal.runtime.conf.ObjectModel;
import org.kie.internal.runtime.manager.InternalRuntimeManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class EjbObjectModelResolver extends ReflectionObjectModelResolver {
private static final Logger logger = LoggerFactory.getLogger(EjbObjectModelResolver.class);
public static final String ID = "ejb";
private Map<String, Class<?>> knownContextParamMapping = new HashMap<String, Class<?>>();
public EjbObjectModelResolver() {
knownContextParamMapping.put("entityManagerFactory", EntityManagerFactory.class);
knownContextParamMapping.put("runtimeManager", RuntimeManager.class);
knownContextParamMapping.put("kieSession", KieServices.class);
knownContextParamMapping.put("taskService", TaskService.class);
knownContextParamMapping.put("executorService", ExecutorService.class);
knownContextParamMapping.put("classLoader", ClassLoader.class);
}
@Override
public Object getInstance(ObjectModel model, ClassLoader cl, Map<String, Object> contextParams) {
Class<?> clazz = getClassObject(model.getIdentifier(), cl);
Object instance = null;
InternalRuntimeManager manager = null;
if (contextParams.containsKey("runtimeManager")) {
manager = (InternalRuntimeManager) contextParams.get("runtimeManager");
instance = manager.getCacheManager().get(clazz.getName());
if (instance != null) {
return instance;
}
}
if (model.getParameters() == null || model.getParameters().isEmpty()) {
logger.debug("About to create instance of {} with no arg constructor", model.getIdentifier());
// no parameters then use no arg constructor
try {
instance = clazz.newInstance();
} catch (Exception e) {
throw new IllegalArgumentException("Unable to create instance (no arg constructor) of type "
+ model.getIdentifier() + " due to " + e.getMessage(), e);
}
} else {
logger.debug("About to create instance of {} with {} parameters", model.getIdentifier(), model.getParameters().size());
// process parameter instances
Class<?>[] parameterTypes = new Class<?>[model.getParameters().size()];
Object[] paramInstances = new Object[model.getParameters().size()];
int index = 0;
for (Object param : model.getParameters()) {
if (param instanceof ObjectModel) {
logger.debug("Parameter is of type ObjectModel (id: {}), trying to create instance based on that model",
((ObjectModel) param).getIdentifier());
Class<?> paramclazz = getClassObject(((ObjectModel)param).getIdentifier(), cl);
parameterTypes[index] = paramclazz;
paramInstances[index] = getInstance(((ObjectModel)param), cl, contextParams);
} else {
if (contextParams.containsKey(param)) {
logger.debug("Parametr references context parametr with name {}", param);
Object contextValue = contextParams.get(param);
Class<?> paramClass = contextValue.getClass();
if (knownContextParamMapping.containsKey(param)) {
paramClass = knownContextParamMapping.get(param);
}
parameterTypes[index] = paramClass;
paramInstances[index] = contextValue;
} else {
if (param.toString().startsWith("jndi:")) {
logger.debug("Parameter is jndi lookup type - {}", param);
// remove the jndi: prefix
String lookupName = param.toString().substring(5);
try {
Object jndiObject = InitialContext.doLookup(lookupName);
parameterTypes[index] = Object.class;
paramInstances[index] = jndiObject;
} catch (NamingException e) {
throw new IllegalArgumentException("Unable to look up object from jndi using name " + lookupName, e);
}
} else {
logger.debug("Parameter is simple type (string) - {}", param);
parameterTypes[index] = param.getClass();
paramInstances[index] = param;
}
}
}
index++;
}
try {
logger.debug("Creating instance of class {} with parameter types {} and parameter instances {}",
clazz, parameterTypes, paramInstances);
Constructor<?> constructor = clazz.getConstructor(parameterTypes);
instance = constructor.newInstance(paramInstances);
} catch (Exception e) {
throw new IllegalArgumentException("Unable to create instance (" + parameterTypes + " constructor) of type "
+ model.getIdentifier() + " due to " + e.getMessage(), e);
}
}
logger.debug("Created instance : {}", instance);
if (manager != null && instance instanceof Cacheable) {
manager.getCacheManager().add(instance.getClass().getName(), instance);
}
return instance;
}
@Override
public boolean accept(String resolverId) {
if (ID.equals(resolverId)) {
return true;
}
logger.debug("Resolver id {} is not accepted by {}", resolverId, this.getClass());
return false;
}
}