Package org.apache.cocoon.components.flow.ws

Source Code of org.apache.cocoon.components.flow.ws.WebServiceLoader$MyClassRepository

/*
* Copyright 1999-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.cocoon.components.flow.ws;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.rmi.Remote;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.wsdl.WSDLException;

import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.axis.utils.JavaUtils;
import org.apache.axis.wsdl.toJava.Namespaces;
import org.apache.axis.wsdl.toJava.Utils;
import org.apache.cocoon.Constants;
import org.apache.cocoon.components.flow.javascript.fom.CompilingClassLoader;
import org.apache.excalibur.source.Source;
import org.apache.excalibur.source.SourceResolver;
import org.apache.excalibur.source.SourceValidity;
import org.apache.excalibur.store.Store;

/**
* Given a WSDL URL generates and compiles client bindings for the requested
* service endpoint.
*/
public class WebServiceLoader extends AbstractLogEnabled implements
        Contextualizable, ThreadSafe, Serviceable {

    protected Logger logger;
    protected Context context;
    protected ServiceManager serviceManager;
    protected CompilingClassLoader classLoader;
    protected MyClassRepository javaClassRepository = new MyClassRepository();
    protected String sourcePath;

    private Store endpointCache = null;

    /**
     * Loads a SOAP endpoint using the first service definition with a SOAP
     * binding found in the referenced WSDL document.
     *
     * @param wsdlURL
     * @return @throws
     *         Exception
     * @throws InvalidServiceException
     * @throws LoadException
     */
    public Remote load(String wsdlURL) throws Exception,
            InvalidServiceException, LoadException {
        return load(wsdlURL, null, null);
    }

    /**
     * Loads a SOAP endpoint using the endpoint identified by the given
     * service/port combination.
     *
     * @param wsdlURL
     * @param serviceName
     * @param portName
     * @return @throws
     *         LoadException
     */
    public Remote load(String wsdlURL, String serviceName, String portName)
            throws LoadException {
        // return endpoint proxy from cache if we have it, should check every so
        // often to see if
        // WSDL has been modifed and regenerate bindings if required
        String key = null;
        if (this.endpointCache != null) {
            key = makeEndpointKey(wsdlURL, serviceName, portName);
            if (this.endpointCache.containsKey(key)) {
                return (Remote) this.endpointCache.get(key);
            }
        }

        // create the endpoint definition
        EndpointDefinition endpointDefn;
        try {
            endpointDefn = new EndpointDefinition(wsdlURL, serviceName,
                    portName);
        } catch (WSDLException e) {
            String msg = "Could not load web service, error reading WSDL";
            throw new LoadException(msg, e);
        } catch (InvalidServiceException e) {
            String msg = "Could not load web service, no valid service declared in WSDL";
            throw new LoadException(msg, e);
        }

        if (!bindingsAreGenerated(endpointDefn.getNamespaceURI(), endpointDefn
                .getServiceName())) {
            generateClientBindings(wsdlURL);
        }

        // instantiate service and return endpoint
        Remote endpoint = getServiceEndPoint(endpointDefn.getServiceName(),
                endpointDefn.getPortName(), endpointDefn.getNamespaceURI());

        // cache the proxy
        if (this.endpointCache != null) {
            try {
                this.endpointCache.store(key, endpoint);
            } catch (IOException e) {
                String msg = "Error storing proxy in endpoint cache";
                this.logger.error(msg);
            }
        }
        return endpoint;
    }

    /**
     * Creates a key that uniquely identifies a SOAP endpoint
     *
     * @param wsdlURL
     * @param serviceName
     * @param portName
     * @return
     */
    private String makeEndpointKey(String wsdlURL, String serviceName,
            String portName) {
        String key = wsdlURL;
        if (serviceName != null) {
            key += serviceName;
        }
        if (portName != null) {
            key += portName;
        }
        return key;
    }

    /**
     * Dynamically instantiates a service locator and uses this to get the
     * endpoint stub
     *
     * @param serviceName
     * @param portName
     * @param namespaceURI
     * @return @throws
     *         LoadException
     */
    private Remote getServiceEndPoint(String serviceName, String portName,
            String namespaceURI) throws LoadException {
        try {
            String serviceLocatorClass = getServiceLocatorClassName(
                    namespaceURI, serviceName);
            Class c = Class
                    .forName(serviceLocatorClass, true, getClassLoader());
            String portAccessorName = getPortAccessorName(c, portName);
            Method m = c.getMethod(portAccessorName, null);
            Remote endpoint = (Remote) m.invoke(c.newInstance(), null);
            return endpoint;
        } catch (Exception e) {
            String msg = "Error loading web service: " + serviceName;
            this.logger.error(msg, e);
            throw new LoadException(msg, e);
        }
    }

    /**
     * Returns the locator class for the requested service
     *
     * @param targetNamespace
     * @param serviceName
     * @return
     */
    private String getServiceLocatorClassName(String targetNamespace,
            String serviceName) {
        String serviceNameCaps = Utils.capitalizeFirstChar(serviceName);
        String packageName = Utils.makePackageName(targetNamespace);
        if (packageName == null) {
            packageName = "";
        } else {
            packageName = packageName + ".";
        }
        String serviceLocatorClassName = packageName + serviceNameCaps
                + "Locator";
        return serviceLocatorClassName;
    }

    /**
     * Returns the accessor method for the requested port
     *
     * @param serviceLocatorClass
     * @param portName
     * @return
     */
    private String getPortAccessorName(Class serviceLocatorClass,
            String portName) throws SecurityException, NoSuchMethodException {
        String portAccessorName = "get"
                + Utils.capitalizeFirstChar(JavaUtils.xmlNameToJava(portName));
        return portAccessorName;
    }

    /**
     * @param wsdlURL
     * @throws LoadException
     */
    private void generateClientBindings(String wsdlURL) throws LoadException {
        ClientBindingGenerator cbg = new ClientBindingGenerator();
        cbg.generate(wsdlURL, this.sourcePath);
    }

    /**
     * Tests if client bindings have been generated for the WSDL.
     *
     * @param wsdlURL
     * @return
     */
    private boolean bindingsAreGenerated(String namespace, String serviceName) {
        try {
            Namespaces namespaces = new Namespaces(this.sourcePath);
            String packageName = Utils.makePackageName(namespace);
            namespaces.put(namespace, packageName);
            String fileName = Utils.capitalizeFirstChar(serviceName) + ".java";
            return Utils.fileExists(fileName, namespace, namespaces);
        } catch (IOException e) {
            logger.error("Error checking for binding class for service: "
                    + serviceName);
        }
        return false;
    }

    /*
     * (non-Javadoc)
     *
     * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
     */
    public void contextualize(final Context context) throws ContextException {
        this.context = context;
        final File workDir = (File) context.get(Constants.CONTEXT_WORK_DIR);
        this.sourcePath = workDir.getAbsolutePath() + File.separator + "axis";

    }

    /*
     * (non-Javadoc)
     *
     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
     */
    public void service(ServiceManager serviceManager) throws ServiceException {
        this.serviceManager = serviceManager;
        try {
            this.endpointCache = (Store) this.serviceManager
                    .lookup(Store.TRANSIENT_STORE);
        } catch (ServiceException e) {
            this.logger.error("Could not find component for role "
                    + Store.TRANSIENT_STORE, e);
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see org.apache.avalon.framework.logger.LogEnabled#enableLogging(org.apache.avalon.framework.logger.Logger)
     */
    public void enableLogging(Logger logger) {
        this.logger = logger;
    }

    private ClassLoader getClassLoader() throws Exception {
        synchronized (this.javaClassRepository) {
            if (this.classLoader == null) {
                this.classLoader = new CompilingClassLoader(Thread
                        .currentThread().getContextClassLoader(),
                        (SourceResolver) WebServiceLoader.this.serviceManager
                                .lookup(SourceResolver.ROLE),
                        this.javaClassRepository);
                this.classLoader
                        .addSourceListener(new CompilingClassLoader.SourceListener() {

                            public void sourceCompiled(Source src) {
                                // no action
                            }

                            public void sourceCompilationError(Source src,
                                    String errMsg) {

                                if (src != null) {
                                    WebServiceLoader.this.logger.error(errMsg);
                                }
                            }
                        });
                updateSourcePath();
            }
            return this.classLoader;
        }
    }

    private void updateSourcePath() {
        if (classLoader != null) {
            classLoader.setSourcePath(new String[] { this.sourcePath });
        }
    }

    class MyClassRepository implements CompilingClassLoader.ClassRepository {

        Map javaSource = new HashMap();
        Map javaClass = new HashMap();
        Map sourceToClass = new HashMap();
        Map classToSource = new HashMap();

        public synchronized void addCompiledClass(String className, Source src,
                byte[] contents) {
            javaSource.put(src.getURI(), src.getValidity());
            javaClass.put(className, contents);
            String uri = src.getURI();
            Set set = (Set) sourceToClass.get(uri);
            if (set == null) {
                set = new HashSet();
                sourceToClass.put(uri, set);
            }
            set.add(className);
            classToSource.put(className, src.getURI());
        }

        public synchronized byte[] getCompiledClass(String className) {
            return (byte[]) javaClass.get(className);
        }

        public synchronized boolean upToDateCheck() throws Exception {
            SourceResolver sourceResolver = (SourceResolver) WebServiceLoader.this.serviceManager
                    .lookup(SourceResolver.ROLE);
            Iterator iter = javaSource.entrySet().iterator();
            List invalid = new LinkedList();
            while (iter.hasNext()) {
                Map.Entry e = (Map.Entry) iter.next();
                String uri = (String) e.getKey();
                SourceValidity validity = (SourceValidity) e.getValue();
                int valid = validity.isValid();
                if (valid == SourceValidity.UNKNOWN) {
                    Source newSrc = null;
                    try {
                        newSrc = sourceResolver.resolveURI(uri);
                        valid = newSrc.getValidity().isValid(validity);
                    } catch (Exception ignored) {
                    } finally {
                        if (newSrc != null) {
                            sourceResolver.release(newSrc);
                        }
                    }
                }
                if (valid != SourceValidity.VALID) {
                    invalid.add(uri);
                }
            }
            iter = invalid.iterator();
            while (iter.hasNext()) {
                String uri = (String) iter.next();
                Set set = (Set) sourceToClass.get(uri);
                Iterator ii = set.iterator();
                while (ii.hasNext()) {
                    String className = (String) ii.next();
                    sourceToClass.remove(className);
                    javaClass.remove(className);
                    classToSource.remove(className);
                }
                set.clear();
                javaSource.remove(uri);
            }
            return invalid.size() == 0;
        }
    }

}
TOP

Related Classes of org.apache.cocoon.components.flow.ws.WebServiceLoader$MyClassRepository

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.