/* * JBoss, Home of Professional Open Source. * Copyright 2009, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.switchboard.mc.resource.provider; import java.util.Collection; import org.jboss.deployers.structure.spi.DeploymentUnit; import org.jboss.logging.Logger; import org.jboss.switchboard.impl.resource.IndependentResource; import org.jboss.switchboard.impl.resource.LinkRefResource; import org.jboss.switchboard.javaee.environment.InjectionTarget; import org.jboss.switchboard.javaee.environment.SimpleEnvironmentEntryType; import org.jboss.switchboard.javaee.util.InjectionTargetUtil; import org.jboss.switchboard.mc.spi.MCBasedResourceProvider; import org.jboss.switchboard.spi.Resource; import org.jboss.switchboard.spi.ResourceProvider; /** * A {@link ResourceProvider} for env-entry in a Java EE environment * * @author Jaikiran Pai * @version $Revision: $ * */ public class EnvEntryResourceProvider implements MCBasedResourceProvider<SimpleEnvironmentEntryType> { /** * Logger */ private static Logger logger = Logger.getLogger(EnvEntryResourceProvider.class); /** * * Processes the passed {@link SimpleEnvironmentEntryType} and creates a {@link Resource} * out of it */ @Override public Resource provide(DeploymentUnit deploymentUnit, SimpleEnvironmentEntryType envEntry) { // Let's check if there's any explicit mapped/lookup name String lookupName = envEntry.getLookupName(); if (lookupName != null && !lookupName.trim().isEmpty()) { return new LinkRefResource(lookupName); } // now check mapped name String mappedName = envEntry.getMappedName(); if (mappedName != null && !mappedName.trim().isEmpty()) { return new LinkRefResource(mappedName); } ClassLoader cl = deploymentUnit.getClassLoader(); // get the env-entry value Object targetValue = this.getEnvEntryValue(cl, envEntry); // create a resource for this target value Resource resource = new IndependentResource(targetValue); // return it! return resource; } @Override public Class<SimpleEnvironmentEntryType> getEnvironmentEntryType() { return SimpleEnvironmentEntryType.class; } /** * Creates and returns the env-entry-value represented by the {@link SimpleEnvironmentEntryType#getValue()} * * @param cl The {@link ClassLoader} to use while processing the metadata * @param envEntry The Java EE env-entry * @return */ private Object getEnvEntryValue(ClassLoader cl, SimpleEnvironmentEntryType envEntry) { // get the (string) value String value = envEntry.getValue(); if (value == null) { return null; } // find out the type of the env-entry Class<?> envEntryType = this.getEnvEntryType(cl, envEntry); if (envEntryType == null) { return value; } // Now, convert the string value to it's appropriate type and return if (envEntryType.equals(String.class)) { return value; } else if (envEntryType.equals(Integer.class) || envEntryType.equals(int.class)) { return new Integer(value); } else if (envEntryType.equals(Long.class) || envEntryType.equals(long.class)) { return new Long(value); } else if (envEntryType.equals(Double.class) || envEntryType.equals(double.class)) { return new Double(value); } else if (envEntryType.equals(Float.class) || envEntryType.equals(float.class)) { return new Float(value); } else if (envEntryType.equals(Byte.class) || envEntryType.equals(byte.class)) { return new Byte(value); } else if (envEntryType.equals(Character.class) || envEntryType.equals(char.class)) { if (value == null || value.length() == 0) { return new Character((char) 0); } else { if (value.length() > 1) { logger.warn("Warning character env-entry is too long: binding=" + envEntry.getName() + " value=" + value); } return new Character(value.charAt(0)); } } else if (envEntryType.equals(Short.class) || envEntryType.equals(short.class)) { return new Short(value); } else if (envEntryType.equals(Boolean.class) || envEntryType.equals(boolean.class)) { return new Boolean(value); } // The Java EE spec doesn't allow java.lang.Class or enum types to be env-entry. // But we (JBoss) will allow these 2 additional types for env-entry. else if (envEntryType.equals(Class.class)) { try { return Class.forName(value, true, cl); } catch (ClassNotFoundException cnfe) { throw new RuntimeException("Could not load class: " + value + " for env-entry: " + envEntry.getName(), cnfe); } } else if (envEntryType.isEnum()) { return Enum.valueOf((Class)envEntryType, value); } else { // TODO: Throw exception instead? return value; } } /** * Returns the env-entry-type for the passed {@link SimpleEnvironmentEntryType}. * <p> * If the passed env-entry has the env-entry-type explicitly specified, then * that value is returned. Else, this method checks for the presence of any * injection targets for this env-entry. If there's a injection target, then * the env-entry-type is deduced based on the field/method of the injection target. * </p> * <p> * This method returns null if the env-entry-type isn't explicitly specified and * if the env-entry-type could not be deduced from the injection targets of this * env-entry. * </p> * * @param cl The {@link ClassLoader} to be used during processing the metadata * @param envEntry The Java EE env-entry * @return */ private Class<?> getEnvEntryType(ClassLoader cl, SimpleEnvironmentEntryType envEntry) { // first check whether the type is explicitly specified String explicitType = envEntry.getType(); if (explicitType != null && !explicitType.trim().isEmpty()) { try { return this.loadClass(explicitType, cl); } catch (ClassNotFoundException cnfe) { throw new RuntimeException("Could not load class: " + explicitType + " for env-entry: " + envEntry.getName(), cnfe); } } Collection<InjectionTarget> injectionTargets = envEntry.getInjectionTargets(); if (injectionTargets == null || injectionTargets.isEmpty()) { return null; } InjectionTarget injectionTarget = injectionTargets.iterator().next(); Class<?> type = InjectionTargetUtil.getInjectionTargetPropertyType(cl, injectionTarget); return type; } private Class<?> loadClass(String className, ClassLoader cl) throws ClassNotFoundException { if (className.equals(void.class.getName())) { return void.class; } if (className.equals(byte.class.getName())) { return byte.class; } if (className.equals(short.class.getName())) { return short.class; } if (className.equals(int.class.getName())) { return int.class; } if (className.equals(long.class.getName())) { return long.class; } if (className.equals(char.class.getName())) { return char.class; } if (className.equals(boolean.class.getName())) { return boolean.class; } if (className.equals(float.class.getName())) { return float.class; } if (className.equals(double.class.getName())) { return double.class; } // Now that we know its not a primitive, lets just allow // the passed classloader to handle the request. // Note that we are intentionally using Class.forName(name,boolean,cl) // to handle issues with loading array types in Java 6 http://bugs.sun.com/view_bug.do?bug_id=6434149 return Class.forName(className, false, cl); } }