| /* |
| * Copyright 2001-2004 The Apache Software Foundation. |
| * |
| * 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.apache.axis; |
| |
| import org.apache.axis.components.logger.LogFactory; |
| import org.apache.axis.utils.Messages; |
| import org.apache.commons.discovery.ResourceClassIterator; |
| import org.apache.commons.discovery.ResourceNameDiscover; |
| import org.apache.commons.discovery.ResourceNameIterator; |
| import org.apache.commons.discovery.resource.ClassLoaders; |
| import org.apache.commons.discovery.resource.classes.DiscoverClasses; |
| import org.apache.commons.discovery.resource.names.DiscoverMappedNames; |
| import org.apache.commons.discovery.resource.names.DiscoverNamesInAlternateManagedProperties; |
| import org.apache.commons.discovery.resource.names.DiscoverNamesInManagedProperties; |
| import org.apache.commons.discovery.resource.names.DiscoverServiceNames; |
| import org.apache.commons.discovery.resource.names.NameDiscoverers; |
| import org.apache.commons.discovery.tools.ClassUtils; |
| import org.apache.commons.discovery.tools.DefaultClassHolder; |
| import org.apache.commons.discovery.tools.DiscoverClass; |
| import org.apache.commons.discovery.tools.ManagedProperties; |
| import org.apache.commons.discovery.tools.PropertiesHolder; |
| import org.apache.commons.discovery.tools.SPInterface; |
| import org.apache.commons.logging.Log; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.security.AccessController; |
| import java.security.PrivilegedAction; |
| import java.util.Enumeration; |
| import java.util.Map; |
| import java.util.Properties; |
| |
| |
| /** |
| * Configuration properties for AXIS. |
| * |
| * <p>Manage configuration properties according to a secure |
| * scheme similar to that used by classloaders: |
| * <ul> |
| * <li><code>ClassLoader</code>s are organized in a tree hierarchy.</li> |
| * <li>each <code>ClassLoader</code> has a reference |
| * to a parent <code>ClassLoader</code>.</li> |
| * <li>the root of the tree is the bootstrap <code>ClassLoader</code>er.</li> |
| * <li>the youngest decendent is the thread context class loader.</li> |
| * <li>properties are bound to a <code>ClassLoader</code> instance |
| * <ul> |
| * <li><i>non-default</i> properties bound to a parent <code>ClassLoader</code> |
| * instance take precedence over all properties of the same name bound |
| * to any decendent. |
| * Just to confuse the issue, this is the default case.</li> |
| * <li><i>default</i> properties bound to a parent <code>ClassLoader</code> |
| * instance may be overriden by (default or non-default) properties of |
| * the same name bound to any decendent. |
| * </li> |
| * </ul> |
| * </li> |
| * <li>System properties take precedence over all other properties</li> |
| * </ul> |
| * |
| * @author Richard A. Sitze |
| */ |
| public class AxisProperties { |
| /** The <code>Log</code> for all interesting events in this class. */ |
| protected static Log log = |
| LogFactory.getLog(AxisProperties.class.getName()); |
| |
| private static DiscoverNamesInAlternateManagedProperties altNameDiscoverer; |
| private static DiscoverMappedNames mappedNames; |
| private static NameDiscoverers nameDiscoverer; |
| private static ClassLoaders loaders; |
| |
| public static void setClassOverrideProperty(Class clazz, String propertyName) { |
| getAlternatePropertyNameDiscoverer() |
| .addClassToPropertyNameMapping(clazz.getName(), propertyName); |
| } |
| |
| public static void setClassDefault(Class clazz, String defaultName) { |
| getMappedNames().map(clazz.getName(), defaultName); |
| } |
| |
| public static void setClassDefaults(Class clazz, String[] defaultNames) { |
| getMappedNames().map(clazz.getName(), defaultNames); |
| } |
| |
| public static synchronized ResourceNameDiscover getNameDiscoverer() { |
| if (nameDiscoverer == null) { |
| nameDiscoverer = new NameDiscoverers(); |
| nameDiscoverer.addResourceNameDiscover(getAlternatePropertyNameDiscoverer()); |
| nameDiscoverer.addResourceNameDiscover(new DiscoverNamesInManagedProperties()); |
| nameDiscoverer.addResourceNameDiscover(new DiscoverServiceNames(getClassLoaders())); |
| nameDiscoverer.addResourceNameDiscover(getMappedNames()); |
| } |
| return nameDiscoverer; |
| } |
| |
| public static ResourceClassIterator getResourceClassIterator(Class spi) { |
| ResourceNameIterator it = getNameDiscoverer().findResourceNames(spi.getName()); |
| return new DiscoverClasses(loaders).findResourceClasses(it); |
| } |
| |
| private static synchronized ClassLoaders getClassLoaders() { |
| if (loaders == null) { |
| loaders = ClassLoaders.getAppLoaders(AxisProperties.class, null, true); |
| } |
| return loaders; |
| } |
| |
| private static synchronized DiscoverMappedNames getMappedNames() { |
| if (mappedNames == null) { |
| mappedNames = new DiscoverMappedNames(); |
| } |
| return mappedNames; |
| } |
| |
| private static synchronized DiscoverNamesInAlternateManagedProperties getAlternatePropertyNameDiscoverer() { |
| if (altNameDiscoverer == null) { |
| altNameDiscoverer = new DiscoverNamesInAlternateManagedProperties(); |
| } |
| |
| return altNameDiscoverer; |
| } |
| |
| /** |
| * Create a new instance of a service provider class. |
| * |
| * !WARNING! |
| * SECURITY issue. |
| * |
| * See bug 11874 |
| * |
| * The solution to both is to move doPrivilege UP within AXIS to a |
| * class that is either private (cannot be reached by code outside |
| * AXIS) or that represents a secure public interface... |
| * |
| * This is going to require analysis and (probably) rearchitecting. |
| * So, I'm taking taking the easy way out until we are at a point |
| * where we can reasonably rearchitect for security. |
| * |
| * @param spiClass the service provider class to instantiate |
| * @return a new instance of this class |
| */ |
| |
| public static Object newInstance(Class spiClass) |
| { |
| return newInstance(spiClass, null, null); |
| } |
| |
| public static Object newInstance(final Class spiClass, |
| final Class constructorParamTypes[], |
| final Object constructorParams[]) { |
| return AccessController.doPrivileged( |
| new PrivilegedAction() { |
| public Object run() { |
| ResourceClassIterator services = getResourceClassIterator(spiClass); |
| |
| Object obj = null; |
| while (obj == null && services.hasNext()) { |
| Class service = services.nextResourceClass().loadClass(); |
| |
| /* service == null |
| * if class resource wasn't loadable |
| */ |
| if (service != null) { |
| /* OK, class loaded.. attempt to instantiate it. |
| */ |
| try { |
| ClassUtils.verifyAncestory(spiClass, service); |
| obj = ClassUtils.newInstance(service, constructorParamTypes, constructorParams); |
| } catch (InvocationTargetException e) { |
| if (e.getTargetException() instanceof java.lang.NoClassDefFoundError) { |
| log.debug(Messages.getMessage("exception00"), e); |
| } else { |
| log.warn(Messages.getMessage("exception00"), e); |
| } |
| } catch (Exception e) { |
| log.warn(Messages.getMessage("exception00"), e); |
| } |
| } |
| } |
| |
| return obj; |
| } |
| }); |
| } |
| |
| |
| /** |
| * Get value for property bound to the current thread context class loader. |
| * |
| * @param propertyName property name. |
| * @return property value if found, otherwise default. |
| */ |
| public static String getProperty(String propertyName) { |
| return ManagedProperties.getProperty(propertyName); |
| } |
| |
| /** |
| * Get value for property bound to the current thread context class loader. |
| * If not found, then return default. |
| * |
| * @param propertyName property name. |
| * @param dephault default value. |
| * @return property value if found, otherwise default. |
| */ |
| public static String getProperty(String propertyName, String dephault) { |
| return ManagedProperties.getProperty(propertyName, dephault); |
| } |
| |
| /** |
| * Set value for property bound to the current thread context class loader. |
| * @param propertyName property name |
| * @param value property value (non-default) If null, remove the property. |
| */ |
| public static void setProperty(String propertyName, String value) { |
| ManagedProperties.setProperty(propertyName, value); |
| } |
| |
| /** |
| * Set value for property bound to the current thread context class loader. |
| * @param propertyName property name |
| * @param value property value. If null, remove the property. |
| * @param isDefault determines if property is default or not. |
| * A non-default property cannot be overriden. |
| * A default property can be overriden by a property |
| * (default or non-default) of the same name bound to |
| * a decendent class loader. |
| */ |
| public static void setProperty(String propertyName, String value, boolean isDefault) { |
| ManagedProperties.setProperty(propertyName, value, isDefault); |
| } |
| |
| /** |
| * Set property values for <code>Properties</code> bound to the |
| * current thread context class loader. |
| * |
| * @param newProperties name/value pairs to be bound |
| */ |
| public static void setProperties(Map newProperties) { |
| ManagedProperties.setProperties(newProperties); |
| } |
| |
| |
| /** |
| * Set property values for <code>Properties</code> bound to the |
| * current thread context class loader. |
| * |
| * @param newProperties name/value pairs to be bound |
| * @param isDefault determines if properties are default or not. |
| * A non-default property cannot be overriden. |
| * A default property can be overriden by a property |
| * (default or non-default) of the same name bound to |
| * a decendent class loader. |
| */ |
| public static void setProperties(Map newProperties, boolean isDefault) { |
| ManagedProperties.setProperties(newProperties, isDefault); |
| } |
| |
| |
| public static Enumeration propertyNames() { |
| return ManagedProperties.propertyNames(); |
| } |
| |
| /** |
| * This is an expensive operation. |
| * |
| * @return Returns a <code>java.util.Properties</code> instance |
| * that is equivalent to the current state of the scoped |
| * properties, in that getProperty() will return the same value. |
| * However, this is a copy, so setProperty on the |
| * returned value will not effect the scoped properties. |
| */ |
| public static Properties getProperties() { |
| return ManagedProperties.getProperties(); |
| } |
| |
| |
| public static Object newInstance(Class spiClass, Class defaultClass) |
| { |
| return newInstance(new SPInterface(spiClass), new DefaultClassHolder(defaultClass)); |
| } |
| |
| /** |
| * !WARNING! |
| * SECURITY issue. |
| * |
| * See bug 11874 |
| * |
| * The solution to both is to move doPrivilege UP within AXIS to a |
| * class that is either private (cannot be reached by code outside |
| * AXIS) or that represents a secure public interface... |
| * |
| * This is going to require analysis and (probably) rearchitecting. |
| * So, I'm taking taking the easy way out until we are at a point |
| * where we can reasonably rearchitect for security. |
| */ |
| private static Object newInstance(final SPInterface spi, |
| final DefaultClassHolder defaultClass) |
| { |
| return AccessController.doPrivileged( |
| new PrivilegedAction() { |
| public Object run() { |
| try { |
| return DiscoverClass.newInstance(null, |
| spi, |
| (PropertiesHolder)null, |
| defaultClass); |
| } catch (Exception e) { |
| log.error(Messages.getMessage("exception00"), e); |
| } |
| return null; |
| } |
| }); |
| } |
| } |