001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.discovery.jdk;
018    
019    import java.io.IOException;
020    import java.net.URL;
021    import java.util.Enumeration;
022    
023    
024    /**
025     * @author Richard A. Sitze
026     */
027    public class JDK11Hooks extends JDKHooks {
028        private static final ClassLoader systemClassLoader
029            = new PsuedoSystemClassLoader();
030    
031        /**
032         * Get the system property
033         *
034         * @param propName name of the property
035         * @return value of the property
036         */
037        public String getSystemProperty(final String propName) {
038            return System.getProperty(propName);
039        }
040    
041        /**
042         * The thread context class loader is available for JDK 1.2
043         * or later, if certain security conditions are met.
044         * 
045         * @return The thread context class loader, if available.
046         *         Otherwise return null.
047         */
048        public ClassLoader getThreadContextClassLoader() {
049            return null;
050        }
051        
052        /**
053         * The system class loader is available for JDK 1.2
054         * or later, if certain security conditions are met.
055         * 
056         * @return The system class loader, if available.
057         *         Otherwise return null.
058         */
059        public ClassLoader getSystemClassLoader() {
060            return systemClassLoader;
061        }
062    
063        /**
064         * Implement ClassLoader.getResources for JDK 1.1
065         * 
066         * On JDK1.1 there is no getResources() method. We emulate this by
067         * using introspection and doing the lookup ourself, using the list
068         * of URLs, via getURLs().
069         */
070        public Enumeration getResources(ClassLoader loader,
071                                        String resourceName)
072            throws IOException
073        {
074            /**
075             * The simple answer is/was:
076             *    return loader.getResources(resourceName);
077             * 
078             * However, some classloaders overload the behavior of getResource
079             * (loadClass, etc) such that the order of returned results changes
080             * from normally expected behavior.
081             * 
082             * Example: locate classes/resources from child ClassLoaders first,
083             *          parents last (in some J2EE environs).
084             * 
085             * The resource returned by getResource() should be the same as the
086             * first resource returned by getResources().  Unfortunately, this
087             * is not, and cannot be: getResources() is 'final' in the current
088             * JDK's (1.2, 1.3, 1.4).
089             * 
090             * To address this, the implementation of this method will
091             * return an Enumeration such that the first element is the
092             * results of getResource, and all trailing elements are
093             * from getResources.  On each iteration, we check so see
094             * if the resource (from getResources) matches the first resource,
095             * and eliminate the redundent element.
096             */
097            
098            final URL first = (URL)loader.getResource(resourceName);
099            final Enumeration rest = loader.getResources(resourceName);
100            
101            return new Enumeration() {
102                private boolean firstDone = (first == null);
103                private URL next = getNext();
104                
105                public Object nextElement() {
106                    URL o = next;
107                    next = getNext();
108                    return o;
109                }
110    
111                public boolean hasMoreElements() {
112                    return next != null;
113                }
114                
115                private URL getNext() {
116                    URL n;
117                    
118                    if (!firstDone) {
119                        /**
120                         * First time through, use results of getReference()
121                         * if they were non-null.
122                         */
123                        firstDone = true;
124                        n = first;
125                    } else {
126                        /**
127                         * Subsequent times through,
128                         * use results of getReferences()
129                         * but take out anything that matches 'first'.
130                         * 
131                         * Iterate through list until we find one that
132                         * doesn't match 'first'.
133                         */
134                        n = null;
135                        while (rest.hasMoreElements()  &&  n == null) {
136                            n = (URL)rest.nextElement();
137                            if (first != null &&
138                                n != null &&
139                                n.equals(first))
140                            {
141                                n = null;
142                            }
143                        }
144                    }
145                    
146                    return n;
147                }
148            };
149        }
150    }