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 */
017package org.apache.commons.discovery.jdk;
018
019import java.io.IOException;
020import java.net.URL;
021import java.util.Enumeration;
022
023/**
024 * JDK 1.1 Style Hooks implementation.
025 */
026public class JDK11Hooks extends JDKHooks {
027
028    private static final ClassLoader systemClassLoader = new PsuedoSystemClassLoader();
029
030    /**
031     * {@inheritDoc}
032     */
033    @Override
034    public String getSystemProperty(final String propName) {
035        return System.getProperty(propName);
036    }
037
038    /**
039     * {@inheritDoc}
040     */
041    @Override
042    public ClassLoader getThreadContextClassLoader() {
043        return null;
044    }
045
046    /**
047     * {@inheritDoc}
048     */
049    @Override
050    public ClassLoader getSystemClassLoader() {
051        return systemClassLoader;
052    }
053
054    /**
055     * {@inheritDoc}
056     */
057    @Override
058    public Enumeration<URL> getResources(ClassLoader loader, String resourceName) throws IOException {
059        /*
060         * The simple answer is/was:
061         *    return loader.getResources(resourceName);
062         * 
063         * However, some classloaders overload the behavior of getResource
064         * (loadClass, etc) such that the order of returned results changes
065         * from normally expected behavior.
066         * 
067         * Example: locate classes/resources from child ClassLoaders first,
068         *          parents last (in some J2EE environs).
069         * 
070         * The resource returned by getResource() should be the same as the
071         * first resource returned by getResources().  Unfortunately, this
072         * is not, and cannot be: getResources() is 'final' in the current
073         * JDK's (1.2, 1.3, 1.4).
074         * 
075         * To address this, the implementation of this method will
076         * return an Enumeration such that the first element is the
077         * results of getResource, and all trailing elements are
078         * from getResources.  On each iteration, we check so see
079         * if the resource (from getResources) matches the first resource,
080         * and eliminate the redundent element.
081         */
082
083        final URL first = loader.getResource(resourceName);
084
085        final Enumeration<URL> rest = loader.getResources(resourceName);
086
087        return new Enumeration<URL>() {
088
089            private boolean firstDone = (first == null);
090
091            private URL next = getNext();
092
093            public URL nextElement() {
094                URL o = next;
095                next = getNext();
096                return o;
097            }
098
099            public boolean hasMoreElements() {
100                return next != null;
101            }
102
103            private URL getNext() {
104                URL n;
105
106                if (!firstDone) {
107                    /*
108                     * First time through, use results of getReference()
109                     * if they were non-null.
110                     */
111                    firstDone = true;
112                    n = first;
113                } else {
114                    /*
115                     * Subsequent times through,
116                     * use results of getReferences()
117                     * but take out anything that matches 'first'.
118                     * 
119                     * Iterate through list until we find one that
120                     * doesn't match 'first'.
121                     */
122                    n = null;
123                    while (rest.hasMoreElements()  &&  n == null) {
124                        n = rest.nextElement();
125                        if (first != null &&
126                            n != null &&
127                            n.equals(first))
128                        {
129                            n = null;
130                        }
131                    }
132                }
133
134                return n;
135            }
136        };
137    }
138
139}