blob: 7b722bbe827e584fc43aec5eeac03ef5aaef225c [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.openejb.config;
import org.apache.commons.lang3.StringUtils;
import org.apache.openejb.OpenEJBException;
import org.apache.openejb.jee.EjbJar;
import org.apache.openejb.jee.EnterpriseBean;
import org.apache.openejb.jee.EnvEntry;
import org.apache.openejb.jee.InjectionTarget;
import org.apache.openejb.jee.JndiConsumer;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* @version $Rev$ $Date$
*/
public class CleanEnvEntries implements DynamicDeployer {
@Override
public AppModule deploy(AppModule appModule) throws OpenEJBException {
// Any EnvEntry types missing the <value> and having no <lookup> should be removed
appModule = removeUnsetEnvEntries(appModule);
// Any EnvEntry types having the <value> but missing the type should have the type implied
// based on the injection points
appModule = fillInMissingType(appModule);
return appModule;
}
public AppModule removeUnsetEnvEntries(AppModule appModule) throws OpenEJBException {
for (ClientModule module : appModule.getClientModules()) {
final JndiConsumer consumer = module.getApplicationClient();
if (consumer == null) continue;
removeUnsetEnvEntries(consumer);
}
for (WebModule module : appModule.getWebModules()) {
final JndiConsumer consumer = module.getWebApp();
if (consumer == null) continue;
removeUnsetEnvEntries(consumer);
}
for (EjbModule module : appModule.getEjbModules()) {
final EjbJar ejbJar = module.getEjbJar();
if (ejbJar == null) continue;
for (EnterpriseBean consumer : ejbJar.getEnterpriseBeans()) {
removeUnsetEnvEntries(consumer);
}
}
return appModule;
}
private void removeUnsetEnvEntries(JndiConsumer consumer) {
final Iterator<EnvEntry> entries = consumer.getEnvEntry().iterator();
while (entries.hasNext()) {
final EnvEntry entry = entries.next();
if (entry.getEnvEntryValue() != null) continue;
if (entry.getLookupName() != null) continue;
entries.remove();
}
}
public AppModule fillInMissingType(AppModule appModule) throws OpenEJBException {
for (ClientModule module : appModule.getClientModules()) {
final JndiConsumer consumer = module.getApplicationClient();
if (consumer == null) continue;
fillInMissingType(consumer, module);
}
for (WebModule module : appModule.getWebModules()) {
final JndiConsumer consumer = module.getWebApp();
if (consumer == null) continue;
fillInMissingType(consumer, module);
}
for (EjbModule module : appModule.getEjbModules()) {
final EjbJar ejbJar = module.getEjbJar();
if (ejbJar == null) continue;
for (EnterpriseBean consumer : ejbJar.getEnterpriseBeans()) {
fillInMissingType(consumer, module);
}
}
return appModule;
}
private void fillInMissingType(JndiConsumer consumer, DeploymentModule module) {
final ClassLoader loader = module.getClassLoader();
for (EnvEntry entry : consumer.getEnvEntry()) {
fillInMissingType(loader, entry);
}
}
private void fillInMissingType(ClassLoader loader, EnvEntry entry) {
if (entry.getType() != null) return;
// If it has the lookup supplied we don't care if there is no type
if (entry.getLookupName() != null) return;
// We can't imply type without at least one injection point
if (entry.getInjectionTarget().size() == 0) return;
final Set<Class> types = new HashSet<Class>();
for (InjectionTarget target : entry.getInjectionTarget()) {
if (target.getInjectionTargetClass() == null) continue;
if (target.getInjectionTargetName() == null) continue;
types.add(getType(loader, target));
}
normalize(types);
final Class<?> type = (types.size() == 1) ? types.iterator().next() : String.class;
entry.setType(type.getName());
}
private void normalize(Set<Class> types) {
types.remove(Object.class);
if (types.contains(int.class)) {
types.remove(int.class);
types.add(Integer.class);
}
if (types.contains(char.class)) {
types.remove(char.class);
types.add(Character.class);
}
if (types.contains(short.class)) {
types.remove(short.class);
types.add(Short.class);
}
if (types.contains(long.class)) {
types.remove(long.class);
types.add(Long.class);
}
if (types.contains(float.class)) {
types.remove(float.class);
types.add(Float.class);
}
if (types.contains(double.class)) {
types.remove(double.class);
types.add(Double.class);
}
if (types.contains(boolean.class)) {
types.remove(boolean.class);
types.add(Boolean.class);
}
if (types.contains(byte.class)) {
types.remove(byte.class);
types.add(Byte.class);
}
}
private Class<?> getType(ClassLoader loader, InjectionTarget target) {
try {
final Class<?> clazz = loader.loadClass(target.getInjectionTargetClass());
try {
final Field field = clazz.getDeclaredField(target.getInjectionTargetName());
return field.getType();
} catch (NoSuchFieldException e) {
}
// TODO Technically we should match by case
final String bestName = "set" + StringUtils.capitalize(target.getInjectionTargetName());
final String name = "set" + target.getInjectionTargetName().toLowerCase();
Class<?> found = null;
for (Method method : clazz.getDeclaredMethods()) {
if (method.getParameterTypes().length == 1) {
if (method.getName().equals(bestName)) {
return method.getParameterTypes()[0];
} else if (method.getName().toLowerCase().equals(name)) {
found = method.getParameterTypes()[0];
}
}
}
if (found != null) {
return found;
}
} catch (Throwable e) {
}
return Object.class;
}
}