You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2010/08/05 21:32:40 UTC

svn commit: r982743 [3/3] - in /myfaces/core/trunk/impl: ./ src/main/java/org/apache/myfaces/commons/ src/main/java/org/apache/myfaces/commons/discovery/ src/main/java/org/apache/myfaces/commons/discovery/jdk/ src/main/java/org/apache/myfaces/commons/d...

Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/EnvironmentCache.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/EnvironmentCache.java?rev=982743&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/EnvironmentCache.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/EnvironmentCache.java Thu Aug  5 19:32:38 2010
@@ -0,0 +1,122 @@
+/*
+ * 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.myfaces.commons.discovery.tools;
+
+import java.util.HashMap;
+
+import org.apache.myfaces.commons.discovery.jdk.JDKHooks;
+
+
+/**
+ * Cache by a 'key' unique to the environment:
+ * 
+ * - ClassLoader::groupContext::Object Cache
+ *         Cache : HashMap
+ *         Key   : Thread Context Class Loader (<code>ClassLoader</code>)
+ *         Value : groupContext::SPI Cache (<code>HashMap</code>)
+ * 
+ * //- groupContext::Object Cache
+ * //         Cache : HashMap
+ * //         Key   : groupContext (<code>String</code>)
+ * //        Value : <code>Object</code>
+ * 
+ * When we 'release', it is expected that the caller of the 'release'
+ * have the same thread context class loader... as that will be used
+ * to identify cached entries to be released.
+ * 
+ * @author Richard A. Sitze
+ */
+public class EnvironmentCache {
+    /**
+     * Allows null key, important as default groupContext is null.
+     * 
+     * We will manage synchronization directly, so all caches are implemented
+     * as HashMap (unsynchronized).
+     * 
+     */
+    private static final HashMap root_cache = new HashMap();
+
+    /**
+     * Initial hash size for SPI's, default just seem TO big today..
+     */
+    public static final int smallHashSize = 13;
+    
+    /**
+     * Get object keyed by classLoader.
+     */
+    public static synchronized Object get(ClassLoader classLoader)
+    {
+        /**
+         * 'null' (bootstrap/system class loader) thread context class loader
+         * is ok...  Until we learn otherwise.
+         */
+        return root_cache.get(classLoader);
+    }
+    
+    /**
+     * Put service keyed by spi & classLoader.
+     */
+    public static synchronized void put(ClassLoader classLoader, Object object)
+    {
+        /**
+         * 'null' (bootstrap/system class loader) thread context class loader
+         * is ok...  Until we learn otherwise.
+         */
+        if (object != null) {
+            root_cache.put(classLoader, object);
+        }
+    }
+
+
+    /********************** CACHE-MANAGEMENT SUPPORT **********************/
+    
+    /**
+     * Release all internal references to previously created service
+     * instances associated with the current thread context class loader.
+     * The <code>release()</code> method is called for service instances that
+     * implement the <code>Service</code> interface.
+     *
+     * This is useful in environments like servlet containers,
+     * which implement application reloading by throwing away a ClassLoader.
+     * Dangling references to objects in that class loader would prevent
+     * garbage collection.
+     */
+    public static synchronized void release() {
+        /**
+         * 'null' (bootstrap/system class loader) thread context class loader
+         * is ok...  Until we learn otherwise.
+         */
+        root_cache.remove(JDKHooks.getJDKHooks().getThreadContextClassLoader());
+    }
+    
+    
+    /**
+     * Release any internal references to a previously created service
+     * instance associated with the current thread context class loader.
+     * If the SPI instance implements <code>Service</code>, then call
+     * <code>release()</code>.
+     */
+    public static synchronized void release(ClassLoader classLoader) {
+        /**
+         * 'null' (bootstrap/system class loader) thread context class loader
+         * is ok...  Until we learn otherwise.
+         */
+        root_cache.remove(classLoader);
+    }
+}

Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/ManagedProperties.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/ManagedProperties.java?rev=982743&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/ManagedProperties.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/ManagedProperties.java Thu Aug  5 19:32:38 2010
@@ -0,0 +1,362 @@
+/*
+ * 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.myfaces.commons.discovery.tools;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.myfaces.commons.discovery.jdk.JDKHooks;
+
+
+
+/**
+ * <p>This class may disappear in the future, or be moved to another project..
+ * </p>
+ * 
+ * <p>Extend the concept of System properties to a hierarchical scheme
+ * based around class loaders.  System properties are global in nature,
+ * so using them easily violates sound architectural and design principles
+ * for maintaining separation between components and runtime environments.
+ * Nevertheless, there is a need for properties broader in scope than
+ * class or class instance scope.
+ * </p>
+ * 
+ * <p>This class is one solution.
+ * </p>
+ * 
+ * <p>Manage 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>
+ * </p>
+ * 
+ * <p>This is not a perfect solution, as it is possible that
+ * different <code>ClassLoader</code>s load different instances of
+ * <code>ScopedProperties</code>.  The 'higher' this class is loaded
+ * within the <code>ClassLoader</code> hierarchy, the more usefull
+ * it will be.
+ * </p>
+ * 
+ * @author Richard A. Sitze
+ */
+public class ManagedProperties {
+    private static Logger log = Logger.getLogger(ManagedProperties.class.getName());
+    public static void setLog(Logger _log) {
+        log = _log;
+    }
+
+    /**
+     * Cache of Properties, keyed by (thread-context) class loaders.
+     * Use <code>HashMap</code> because it allows 'null' keys, which
+     * allows us to account for the (null) bootstrap classloader.
+     */
+    private static final HashMap propertiesCache = new HashMap();
+    
+                                                        
+    /**
+     * 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 getProperty(getThreadContextClassLoader(), 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 getProperty(getThreadContextClassLoader(), propertyName, dephault);
+    }
+    
+    /**
+     * Get value for property bound to the class loader.
+     * 
+     * @param classLoader
+     * @param propertyName property name.
+     * @return property value if found, otherwise default.
+     */
+    public static String getProperty(ClassLoader classLoader, String propertyName) {
+        String value = JDKHooks.getJDKHooks().getSystemProperty(propertyName);
+        if (value == null) {
+            Value val = getValueProperty(classLoader, propertyName);
+            if (val != null) {
+                value = val.value;
+            }
+        } else if (log.isLoggable(Level.FINE)) {
+            log.fine("found System property '" + propertyName + "'" +
+                      " with value '" + value + "'.");
+        }
+        return value;
+    }
+    
+    /**
+     * Get value for property bound to the class loader.
+     * If not found, then return default.
+     * 
+     * @param classLoader
+     * @param propertyName property name.
+     * @param dephault default value.
+     * @return property value if found, otherwise default.
+     */
+    public static String getProperty(ClassLoader classLoader, String propertyName, String dephault) {
+        String value = getProperty(classLoader, propertyName);
+        return (value == null) ? dephault : value;
+    }
+
+    /**
+     * 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) {
+        setProperty(propertyName, value, false);
+    }
+    
+    /**
+     * 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) {
+        if (propertyName != null) {
+            synchronized (propertiesCache) {
+                ClassLoader classLoader = getThreadContextClassLoader();
+                HashMap properties = (HashMap)propertiesCache.get(classLoader);
+                
+                if (value == null) {
+                    if (properties != null) {
+                        properties.remove(propertyName);
+                    }
+                } else {
+                    if (properties == null) {
+                        properties = new HashMap();
+                        propertiesCache.put(classLoader, properties);
+                    }
+
+                    properties.put(propertyName, new Value(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) {
+        setProperties(newProperties, false);
+    }
+    
+    
+    /**
+     * 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) {
+        java.util.Iterator it = newProperties.entrySet().iterator();
+
+        /**
+         * Each entry must be mapped to a Property.
+         * 'setProperty' does this for us.
+         */
+        while (it.hasNext()) {
+            Map.Entry entry = (Map.Entry)it.next();
+            setProperty( String.valueOf(entry.getKey()),
+                         String.valueOf(entry.getValue()),
+                         isDefault);
+        }
+    }
+
+    
+    /**
+     * Return list of all property names.  This is an expensive
+     * operation: ON EACH CALL it walks through all property lists 
+     * associated with the current context class loader upto
+     * and including the bootstrap class loader.
+     */
+    public static Enumeration propertyNames() {
+        Hashtable allProps = new Hashtable();
+
+        ClassLoader classLoader = getThreadContextClassLoader();
+
+        /**
+         * Order doesn't matter, we are only going to use
+         * the set of all keys...
+         */
+        while (true) {
+            HashMap properties = null;
+
+            synchronized (propertiesCache) {
+                properties = (HashMap)propertiesCache.get(classLoader);
+            }
+
+            if (properties != null) {
+                allProps.putAll(properties);
+            }
+
+            if (classLoader == null) break;
+            
+            classLoader = getParent(classLoader);
+        }
+        
+        return allProps.keys();
+    }
+    
+    /**
+     * This is an expensive operation.
+     * ON EACH CALL it walks through all property lists 
+     * associated with the current context class loader upto
+     * and including the bootstrap class loader.
+     * 
+     * @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() {
+        Properties p = new Properties();
+        
+        Enumeration names = propertyNames();
+        while (names.hasMoreElements()) {
+            String name = (String)names.nextElement();
+            p.put(name, getProperty(name));
+        }
+        
+        return p;
+    }
+
+
+    /***************** INTERNAL IMPLEMENTATION *****************/
+
+    private static class Value {
+        final String value;
+        final boolean isDefault;
+        
+        Value(String value, boolean isDefault) {
+            this.value = value;
+            this.isDefault = isDefault;
+        }
+    }
+
+    /**
+     * Get value for properties bound to the class loader.
+     * Explore up the tree first, as higher-level class
+     * loaders take precedence over lower-level class loaders.
+     */
+    private static final Value getValueProperty(ClassLoader classLoader, String propertyName) {
+        Value value = null;
+
+        if (propertyName != null) {
+            /**
+             * If classLoader isn't bootstrap loader (==null),
+             * then get up-tree value.
+             */
+            if (classLoader != null) {
+                value = getValueProperty(getParent(classLoader), propertyName);
+            }
+            
+            if (value == null  ||  value.isDefault) {
+                synchronized (propertiesCache) {
+                    HashMap properties = (HashMap)propertiesCache.get(classLoader);
+                        
+                    if (properties != null) {
+                        Value altValue = (Value)properties.get(propertyName);
+                        
+                        // set value only if override exists..
+                        // otherwise pass default (or null) on..
+                        if (altValue != null) {
+                            value = altValue;
+
+                            if (log.isLoggable(Level.FINE)) {
+                                log.fine("found Managed property '" + propertyName + "'" +
+                                          " with value '" + value + "'" +
+                                          " bound to classloader " + classLoader + ".");
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        
+        return value;
+    }
+    
+    private static final ClassLoader getThreadContextClassLoader() {
+        return JDKHooks.getJDKHooks().getThreadContextClassLoader();
+    }
+
+    private static final ClassLoader getParent(final ClassLoader classLoader) {
+        return (ClassLoader)AccessController.doPrivileged(new PrivilegedAction() {
+                    public Object run() {
+                        try {
+                            return classLoader.getParent();
+                        } catch (SecurityException se){
+                            return null;
+                        }
+                    }
+                });
+    }
+}

Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/PropertiesHolder.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/PropertiesHolder.java?rev=982743&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/PropertiesHolder.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/PropertiesHolder.java Thu Aug  5 19:32:38 2010
@@ -0,0 +1,67 @@
+/*
+ * 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.myfaces.commons.discovery.tools;
+
+import java.util.Properties;
+
+import org.apache.myfaces.commons.discovery.resource.ClassLoaders;
+
+
+/**
+ * Holder for a default class.
+ * 
+ * Class may be specified by name (String) or class (Class).
+ * Using the holder complicates the users job, but minimized # of API's.
+ * 
+ * @author Richard A. Sitze
+ */
+public class PropertiesHolder {
+    private Properties   properties;
+    private final String propertiesFileName;
+    
+    public PropertiesHolder(Properties properties) {
+        this.properties = properties;
+        this.propertiesFileName = null;
+    }
+    
+    public PropertiesHolder(String propertiesFileName) {
+        this.properties = null;
+        this.propertiesFileName = propertiesFileName;
+    }
+
+    /**
+     * @param spi Optional SPI (may be null).
+     *            If provided, an attempt is made to load the
+     *            property file as-per Class.getResource().
+     * 
+     * @param loaders Used only if properties need to be loaded.
+     * 
+     * @return Properties.  Load the properties if necessary.
+     */
+    public Properties getProperties(SPInterface spi, ClassLoaders loaders) {
+        if (properties == null) {
+            properties = ResourceUtils.loadProperties(spi.getSPClass(), getPropertiesFileName(), loaders);
+        }
+        return properties;
+    }
+
+    public String getPropertiesFileName() {
+        return propertiesFileName;
+    }
+}

Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/ResourceUtils.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/ResourceUtils.java?rev=982743&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/ResourceUtils.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/ResourceUtils.java Thu Aug  5 19:32:38 2010
@@ -0,0 +1,153 @@
+/*
+ * 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.myfaces.commons.discovery.tools;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import org.apache.myfaces.commons.discovery.DiscoveryException;
+import org.apache.myfaces.commons.discovery.Resource;
+import org.apache.myfaces.commons.discovery.ResourceIterator;
+import org.apache.myfaces.commons.discovery.resource.ClassLoaders;
+import org.apache.myfaces.commons.discovery.resource.DiscoverResources;
+
+
+/**
+ * Mechanisms to locate and load a class.
+ * The load methods locate a class only.
+ * The find methods locate a class and verify that the
+ * class implements an given interface or extends a given class.
+ * 
+ * @author Richard A. Sitze
+ * @author Craig R. McClanahan
+ * @author Costin Manolache
+ */
+public class ResourceUtils {
+    /**
+     * Get package name.
+     * Not all class loaders 'keep' package information,
+     * in which case Class.getPackage() returns null.
+     * This means that calling Class.getPackage().getName()
+     * is unreliable at best.
+     */
+    public static String getPackageName(Class clazz) {
+        Package clazzPackage = clazz.getPackage();
+        String packageName;
+        if (clazzPackage != null) {
+            packageName = clazzPackage.getName();
+        } else {
+            String clazzName = clazz.getName();
+            packageName = new String(clazzName.toCharArray(), 0, clazzName.lastIndexOf('.'));
+        }
+        return packageName;
+    }
+    
+    
+    /**
+     * Load the resource <code>resourceName</code>.
+     * Try each classloader in succession,
+     * until first succeeds, or all fail.
+     * If all fail and <code>resouceName</code> is not absolute
+     * (doesn't start with '/' character), then retry with
+     * <code>packageName/resourceName</code> after changing all
+     * '.' to '/'.
+     * 
+     * @param resourceName The name of the resource to load.
+     */
+    public static Resource getResource(Class spi,
+                                       String resourceName,
+                                       ClassLoaders loaders)
+        throws DiscoveryException
+    {
+        DiscoverResources explorer = new DiscoverResources(loaders);
+        ResourceIterator resources = explorer.findResources(resourceName);
+        
+        if (spi != null  &&
+            !resources.hasNext()  &&
+            resourceName.charAt(0) != '/')
+        {
+            /**
+             * If we didn't find the resource, and if the resourceName
+             * isn't an 'absolute' path name, then qualify with
+             * package name of the spi.
+             */
+            resourceName = getPackageName(spi).replace('.','/') + "/" + resourceName;
+            resources = explorer.findResources(resourceName);
+        }
+        
+        return resources.hasNext()
+               ? resources.nextResource()
+               : null;
+    }
+    
+    /**
+     * Load named property file, optionally qualifed by spi's package name
+     * as per Class.getResource.
+     * 
+     * A property file is loaded using the following sequence of class loaders:
+     *   <ul>
+     *     <li>Thread Context Class Loader</li>
+     *     <li>DiscoverSingleton's Caller's Class Loader</li>
+     *     <li>SPI's Class Loader</li>
+     *     <li>DiscoverSingleton's (this class) Class Loader</li>
+     *     <li>System Class Loader</li>
+     *   </ul>
+     * 
+     * @param propertiesFileName The property file name.
+     * 
+     * @return Instance of a class implementing the SPI.
+     * 
+     * @exception DiscoveryException Thrown if the name of a class implementing
+     *            the SPI cannot be found, if the class cannot be loaded and
+     *            instantiated, or if the resulting class does not implement
+     *            (or extend) the SPI.
+     */    
+    public static Properties loadProperties(Class spi,
+                                            String propertiesFileName,
+                                            ClassLoaders classLoaders)
+        throws DiscoveryException
+    {
+        Properties properties = null;
+        
+        if (propertiesFileName != null) {
+            try {
+                Resource resource = getResource(spi, propertiesFileName, classLoaders);
+                if (resource != null) {
+                    InputStream stream = resource.getResourceAsStream();
+        
+                    if (stream != null) {
+                        properties = new Properties();
+                        try {
+                            properties.load(stream);
+                        } finally {
+                            stream.close();
+                        }
+                    }
+                }
+            } catch (IOException e) {
+                // ignore
+            } catch (SecurityException e) {
+                // ignore
+            }
+        }
+        
+        return properties;
+    }
+}

Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/SPInterface.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/SPInterface.java?rev=982743&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/SPInterface.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/SPInterface.java Thu Aug  5 19:32:38 2010
@@ -0,0 +1,160 @@
+/*
+ * 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.myfaces.commons.discovery.tools;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.myfaces.commons.discovery.DiscoveryException;
+
+
+/**
+ * Represents a Service Programming Interface (spi).
+ * - SPI's name
+ * - SPI's (provider) class
+ * - SPI's (alternate) override property name
+ * 
+ * In addition, while there are many cases where this is NOT
+ * usefull, for those in which it is:
+ * 
+ * - expected constructor argument types and parameters values.
+ * 
+ * @author Richard A. Sitze
+ */
+public class SPInterface {
+    /**
+     * The service programming interface: intended to be
+     * an interface or abstract class, but not limited
+     * to those two.
+     */        
+    private final Class spi;
+    
+    /**
+     * The property name to be used for finding the name of
+     * the SPI implementation class.
+     */
+    private final String propertyName;
+    
+    
+    private Class  paramClasses[] = null;
+    private Object params[] = null;
+
+
+    /**
+     * Construct object representing Class <code>provider</code>.
+     * 
+     * @param provider The SPI class
+     */
+    public SPInterface(Class provider) {
+        this(provider, provider.getName());
+    }
+    
+    /**
+     * Construct object representing Class <code>provider</code>.
+     * 
+     * @param spi The SPI class
+     * 
+     * @param propertyName when looking for the name of a class implementing
+     *        the provider class, a discovery strategy may involve looking for
+     *        (system or other) properties having either the name of the class
+     *        (provider) or the <code>propertyName</code>.
+     */
+    public SPInterface(Class spi, String propertyName) {
+        this.spi = spi;
+        this.propertyName = propertyName;
+    }
+
+    /**
+     * Construct object representing Class <code>provider</code>.
+     * 
+     * @param provider The SPI class
+     * 
+     * @param constructorParamClasses classes representing the
+     *        constructor argument types.
+     * 
+     * @param constructorParams objects representing the
+     *        constructor arguments.
+     */
+    public SPInterface(Class provider,
+                       Class constructorParamClasses[],
+                       Object constructorParams[])
+    {
+        this(provider,
+             provider.getName(),
+             constructorParamClasses,
+             constructorParams);
+    }
+    
+    /**
+     * Construct object representing Class <code>provider</code>.
+     * 
+     * @param spi The SPI class
+     * 
+     * @param propertyName when looking for the name of a class implementing
+     *        the provider class, a discovery strategy may involve looking for
+     *        (system or other) properties having either the name of the class
+     *        (provider) or the <code>propertyName</code>.
+     * 
+     * @param constructorParamClasses classes representing the
+     *        constructor argument types.
+     * 
+     * @param constructorParams objects representing the
+     *        constructor arguments.
+     */
+    public SPInterface(Class spi,
+                       String propertyName,
+                       Class constructorParamClasses[],
+                       Object constructorParams[])
+    {
+        this.spi = spi;
+        this.propertyName = propertyName;
+        this.paramClasses = constructorParamClasses;
+        this.params = constructorParams;
+    }
+
+    public String getSPName() {
+        return spi.getName();
+    }
+
+    public Class getSPClass() {
+        return spi;
+    }
+    
+    public String getPropertyName() {
+        return propertyName;
+    }
+
+    /**
+     * Instantiate a new 
+     */    
+    public Object newInstance(Class impl)
+        throws DiscoveryException,
+               InstantiationException,
+               IllegalAccessException,
+               NoSuchMethodException,
+               InvocationTargetException
+    {
+        verifyAncestory(impl);
+        
+        return ClassUtils.newInstance(impl, paramClasses, params);
+    }
+    
+    public void verifyAncestory(Class impl) {
+        ClassUtils.verifyAncestory(spi, impl);
+    }
+}

Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/Service.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/Service.java?rev=982743&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/Service.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/commons/discovery/tools/Service.java Thu Aug  5 19:32:38 2010
@@ -0,0 +1,123 @@
+/*
+ * 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.myfaces.commons.discovery.tools;
+
+import java.util.Enumeration;
+
+import org.apache.myfaces.commons.discovery.ResourceClass;
+import org.apache.myfaces.commons.discovery.ResourceClassIterator;
+import org.apache.myfaces.commons.discovery.ResourceNameIterator;
+import org.apache.myfaces.commons.discovery.resource.ClassLoaders;
+import org.apache.myfaces.commons.discovery.resource.classes.DiscoverClasses;
+import org.apache.myfaces.commons.discovery.resource.names.DiscoverServiceNames;
+
+
+/**
+ * [this was ServiceDiscovery12... the 1.1 versus 1.2 issue
+ * has been abstracted to org.apache.commons.discover.jdk.JDKHooks]
+ * 
+ * <p>Implement the JDK1.3 'Service Provider' specification.
+ * ( http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html )
+ * </p>
+ *
+ * This class supports any VM, including JDK1.1, via
+ * org.apache.commons.discover.jdk.JDKHooks.
+ *
+ * The caller will first configure the discoverer by adding ( in the desired
+ * order ) all the places to look for the META-INF/services. Currently
+ * we support loaders.
+ *
+ * The findResources() method will check every loader.
+ *
+ * @author Richard A. Sitze
+ * @author Craig R. McClanahan
+ * @author Costin Manolache
+ * @author James Strachan
+ */
+public class Service
+{
+    /** Construct a new service discoverer
+     */
+    protected Service() {
+    }
+    
+    /**
+     * as described in
+     * sun/jdk1.3.1/docs/guide/jar/jar.html#Service Provider,
+     * Except this uses <code>Enumeration</code>
+     * instead of <code>Interator</code>.
+     * 
+     * @return Enumeration of class instances (<code>Object</code>)
+     */
+    public static Enumeration providers(Class spiClass) {
+        return providers(new SPInterface(spiClass), null);
+    }
+    
+    /**
+     * This version lets you specify constructor arguments..
+     * 
+     * @param spi SPI to look for and load.
+     * @param loaders loaders to use in search.
+     *        If <code>null</code> then use ClassLoaders.getAppLoaders().
+     */
+    public static Enumeration providers(final SPInterface spi,
+                                        ClassLoaders loaders)
+    {
+        if (loaders == null) {
+            loaders = ClassLoaders.getAppLoaders(spi.getSPClass(),
+                                                 Service.class,
+                                                 true);
+        }
+        
+        ResourceNameIterator servicesIter =
+            (new DiscoverServiceNames(loaders)).findResourceNames(spi.getSPName());
+
+        final ResourceClassIterator services =
+            (new DiscoverClasses(loaders)).findResourceClasses(servicesIter);
+        
+        return new Enumeration() {
+            private Object object = null;
+            
+            public boolean hasMoreElements() {
+                if (object == null) {
+                    object = getNextClassInstance();
+                }
+                return object != null;
+            }
+            
+            public Object nextElement() {
+                Object obj = object;
+                object = null;
+                return obj;
+            }
+
+            private Object getNextClassInstance() {
+                while (services.hasNext()) {
+                    ResourceClass info = services.nextResourceClass();
+                    try {
+                        return spi.newInstance(info.loadClass());
+                    } catch (Exception e) {
+                        // ignore
+                    }
+                }
+                return null;
+            }
+        };
+    }
+}

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/annotation/DefaultLifecycleProviderFactory.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/annotation/DefaultLifecycleProviderFactory.java?rev=982743&r1=982742&r2=982743&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/annotation/DefaultLifecycleProviderFactory.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/annotation/DefaultLifecycleProviderFactory.java Thu Aug  5 19:32:38 2010
@@ -25,10 +25,10 @@ import java.security.PrivilegedActionExc
 import java.security.PrivilegedExceptionAction;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import org.apache.commons.discovery.resource.ClassLoaders;
-import org.apache.commons.discovery.resource.names.DiscoverServiceNames;
-import org.apache.commons.discovery.ResourceNameIterator;
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
+import org.apache.myfaces.commons.discovery.ResourceNameIterator;
+import org.apache.myfaces.commons.discovery.resource.ClassLoaders;
+import org.apache.myfaces.commons.discovery.resource.names.DiscoverServiceNames;
 import org.apache.myfaces.shared_impl.util.ClassUtils;
 
 import javax.faces.FacesException;
@@ -37,9 +37,6 @@ import javax.naming.Context;
 import javax.naming.InitialContext;
 import javax.naming.NamingException;
 
-import org.apache.commons.discovery.ResourceNameIterator;
-import org.apache.commons.discovery.resource.ClassLoaders;
-import org.apache.commons.discovery.resource.names.DiscoverServiceNames;
 import org.apache.myfaces.shared_impl.util.ClassUtils;
 
 /*

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/annotation/LifecycleProviderFactory.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/annotation/LifecycleProviderFactory.java?rev=982743&r1=982742&r2=982743&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/annotation/LifecycleProviderFactory.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/annotation/LifecycleProviderFactory.java Thu Aug  5 19:32:38 2010
@@ -21,7 +21,7 @@ package org.apache.myfaces.config.annota
 import java.security.AccessController;
 import java.security.PrivilegedActionException;
 
-import org.apache.commons.discovery.tools.DiscoverSingleton;
+import org.apache.myfaces.commons.discovery.tools.DiscoverSingleton;
 
 
 import javax.faces.FacesException;

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/webapp/StartupServletContextListener.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/webapp/StartupServletContextListener.java?rev=982743&r1=982742&r2=982743&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/webapp/StartupServletContextListener.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/webapp/StartupServletContextListener.java Thu Aug  5 19:32:38 2010
@@ -37,8 +37,8 @@ import javax.servlet.http.HttpSessionBin
 import javax.servlet.http.HttpSessionEvent;
 import javax.servlet.http.HttpSessionListener;
 
-import org.apache.commons.discovery.tools.DiscoverSingleton;
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
+import org.apache.myfaces.commons.discovery.tools.DiscoverSingleton;
 import org.apache.myfaces.shared_impl.util.ClassUtils;
 
 /**