All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.tuscany.sca.extensibility.ContextClassLoaderServiceDiscoverer Maven / Gradle / Ivy

The newest version!
/*
 * 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.tuscany.sca.extensibility;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * A ServiceDiscoverer that find META-INF/services/... using the Context ClassLoader.
 *
 * @version $Rev: 993613 $ $Date: 2010-09-07 22:55:44 -0700 (Tue, 07 Sep 2010) $
 */
public class ContextClassLoaderServiceDiscoverer implements ServiceDiscoverer {
    private static final Logger logger = Logger.getLogger(ContextClassLoaderServiceDiscoverer.class.getName());

    public class ServiceDeclarationImpl implements ServiceDeclaration {
        private URL url;
        private String className;
        private Class javaClass;
        private Map attributes;

        public ServiceDeclarationImpl(URL url, String className, Map attributes) {
            super();
            this.url = url;
            this.className = className;
            this.attributes = attributes;
        }

        public Map getAttributes() {
            return attributes;
        }

        public String getClassName() {
            return className;
        }

        public URL getLocation() {
            return url;
        }

        public Class loadClass() throws ClassNotFoundException {
            if (className == null) {
                return null;
            }
            if (javaClass == null) {
                javaClass = loadClass(className);
            }
            return javaClass;
        }

        public Class loadClass(String className) throws ClassNotFoundException {
            return Class.forName(className, false, classLoaderReference.get());
        }

        @Override
        public String toString() {
            StringBuffer sb = new StringBuffer();
            sb.append("Location: ").append(url);
            sb.append(" ClassLoader: ").append(classLoaderReference.get());
            sb.append(" Attributes: ").append(attributes);
            return sb.toString();
        }

        public URL getResource(final String name) {
            return AccessController.doPrivileged(new PrivilegedAction() {
                public URL run() {
                    return classLoaderReference.get().getResource(name);
                }
            });
        }

        public boolean isAssignableTo(Class serviceType) {
            try {
                loadClass();
            } catch (ClassNotFoundException e) {
                // Ignore 
            }
            return (javaClass != null && serviceType.isAssignableFrom(javaClass));
        }

        @Override
        public Enumeration getResources(String name) throws IOException {
            return Collections.enumeration(ContextClassLoaderServiceDiscoverer.this.getResources(name));
        }
    }

    private WeakReference classLoaderReference;

    public ContextClassLoaderServiceDiscoverer() {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        this.classLoaderReference = new WeakReference(classLoader);
    }
    
    public ContextClassLoaderServiceDiscoverer(ClassLoader classLoader) {
        if (classLoader == null) {
            classLoader = Thread.currentThread().getContextClassLoader();
        }
        this.classLoaderReference = new WeakReference(classLoader);
    }
    
    public ClassLoader getContextClassLoader() {
        //return classLoaderReference.get();
        return Thread.currentThread().getContextClassLoader();
    }

    private Collection getResources(final String name) throws IOException {
        try {
            return AccessController.doPrivileged(new PrivilegedExceptionAction>() {
                public Collection run() throws IOException {
                    List urls = Collections.list(classLoaderReference.get().getResources(name));
                    // Eliminate the duplicate URLs (which can be found from child/parent classloaders)
                    return new HashSet(urls);
                }
            });
        } catch (PrivilegedActionException e) {
            throw (IOException)e.getException();
        }
    }

    public ServiceDeclaration getServiceDeclaration(String name) throws IOException {
        Collection declarations = getServiceDeclarations(name);
        if (declarations.isEmpty()) {
            return null;
        } else {
            return declarations.iterator().next();
        }
    }

    public Collection getServiceDeclarations(String serviceName) {
        Collection descriptors = new HashSet();

        // http://java.sun.com/j2se/1.5.0/docs/api/javax/xml/xpath/XPathFactory.html
        boolean isPropertyFile = "javax.xml.xpath.XPathFactory".equals(serviceName);
        
        String name = serviceName;
        if (serviceName.startsWith("/")) {
            // If the service name starts with /, treat it as the entry name
            name = serviceName.substring(1);
        } else {
            // Use JDK SPI pattern
            name = "META-INF/services/" + serviceName;
        }
        
        boolean debug = logger.isLoggable(Level.FINE);
        try {
            for (final URL url : getResources(name)) {
                if (debug) {
                    logger.fine("Reading service provider file: " + url.toExternalForm());
                }

                for (Map attributes : ServiceDeclarationParser.load(url, isPropertyFile)) {
                    String className = attributes.get("class");
                    ServiceDeclarationImpl descriptor = new ServiceDeclarationImpl(url, className, attributes);
                    descriptors.add(descriptor);
                }
            }
        } catch (IOException e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
        }
        return descriptors;

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy