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

org.apache.cocoon.components.axis.providers.AvalonProvider Maven / Gradle / Ivy

/*
 * 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.axis.providers.java;
// currently part of Cocoon until it's officially in Axis CVS (BZ#12903)
package org.apache.cocoon.components.axis.providers;

import org.apache.avalon.framework.service.ServiceManager;

import org.apache.axis.AxisFault;
import org.apache.axis.MessageContext;
import org.apache.axis.providers.java.RPCProvider;
import org.apache.axis.handlers.soap.SOAPService;

import java.lang.reflect.Method;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

import javax.xml.rpc.server.ServiceLifecycle;

/**
 * Provider class which allows you to specify an Avalon ROLE for
 * servicing Axis SOAP requests.
 *
 * 

* The specified ROLE corresponds to a particular implementation * which is retrieved by a given Avalon ServiceManager. * For more information about Avalon, see the Avalon. * website. *

* *

* To use this class, you need to add your Avalon ServiceManager * instance to the MessageContext that is Axis uses to process * messages with. *

* *

* To do this you could for example subclass the AxisServlet and override the * createMessageContext() method adding the ServiceManager, eg: * *

 *   protected MessageContext createMessageContext(...)
 *   {
 *      MessageContext context = super.createMessageContext();
 *      context.setProperty(AvalonProvider.COMPONENT_MANAGER, m_manager);
 *      return context;
 *   }
 *  
* * and appropriately add the AvalonProvider to the list of handlers in your * server-config.wsdd (suggestions on how to improve this are welcomed) *

* *

* This provider will use that ServiceManager reference to * retrieve objects. *

* *

* In your deployment descriptor use the following syntax: * *

 *  <service name="myservice" provider="java:Avalon">
 *    <parameter name="role" value="my.avalon.role.name"/>
 *    <parameter name="className" value="my.avalon.roles.interface.name"/>
 *    <parameter name="allowedMethods" value="allowed.methods"/>
 *  </service>
 * 
* *

* * @version $Id: AvalonProvider.java 587757 2007-10-24 02:52:49Z vgritsenko $ */ public class AvalonProvider extends RPCProvider { /** * Constant used to retrieve the ServiceManager reference * from the MessageContext object. */ public static final String SERVICE_MANAGER = "service-manager"; /** * Constant which represents the name of the ROLE this * provider should lookup to service a request with. This is * specified in the <parameter name="" value=""/> part of the * deployment xml. */ public static final String ROLE = "role"; /** * Returns the service object. * * @param msgContext the message context * @param role the Avalon ROLE to lookup to find the service object implementation * @return an object that implements the service * @exception Exception if an error occurs */ protected Object makeNewServiceObject(MessageContext msgContext, String role) throws Exception { ServiceManager manager = (ServiceManager) msgContext.getProperty(SERVICE_MANAGER); if (manager == null) { throw new AxisFault("Could not access Avalon ServiceManager"); } return decorate(manager.lookup(role), manager); } /** * Helper method for decorating a Component with a Handler * proxy (see below). * * @param object a Component instance * @param manager a ServiceManager instance * @return the Proxy wrapped Component instance * @exception Exception if an error occurs */ private Object decorate(final Object object, final ServiceManager manager) throws Exception { // obtain a list of all interfaces this object implements Class[] interfaces = object.getClass().getInterfaces(); // add ServiceLifecycle to it Class[] adjusted = new Class[ interfaces.length + 1 ]; System.arraycopy(interfaces, 0, adjusted, 0, interfaces.length); adjusted[interfaces.length] = ServiceLifecycle.class; // create a proxy implementing those interfaces Object proxy = Proxy.newProxyInstance( this.getClass().getClassLoader(), adjusted, new Handler(object, manager) ); // return the proxy return proxy; } /** * Return the option in the configuration that contains the service class * name. In the Avalon case, it is the ROLE name to lookup. */ protected String getServiceClassNameOptionName() { return ROLE; } /** * Get the service class description * * @param role the Avalon ROLE name * @param service a SOAPService instance * @param msgContext the message context * @return service class description * @exception AxisFault if an error occurs */ protected Class getServiceClass( String role, SOAPService service, MessageContext msgContext ) throws AxisFault { // Assuming CocoonServiceManager semantics the ROLE name is // actually the class name, potentially with a variant following // the class name with a '/' separator try { int i; if ((i = role.indexOf('/')) != -1) { return Class.forName(role.substring(0, i)); } return Class.forName(role); } catch (ClassNotFoundException e) { throw new AxisFault("Couldn't create class object for role " + role, e); } } /** * InvocationHandler class for managing Avalon * Components. * *

* Components retrieved from an Avalon ServiceManager must be * returned to the manager when they are no longer required. *

* *

* The returning of Components to their ServiceManager is handled * by a Proxy class which uses the following InvocationHandler. *

* *

* Each Component returned by this Provider is wrapped inside a * Proxy class which implements all of the Component's interfaces * including javax.xml.rpc.server.ServiceLifecycle. *

* *

* When Axis is finished with the object returned by this provider, * it invokes ServiceLifecycle.destroy(). This is intercepted by the * InvocationHandler and the Component is returned at this time back * to the ServiceManager it was retrieved from. *

* *

* Note, when Axis invokes ServiceLifecycle.destroy() is dependant * on the scope of the service (ie. Request, Session & Application). *

*/ final class Handler implements InvocationHandler { // Constants describing the ServiceLifecycle.destroy method private final String SL_DESTROY = "destroy"; private final Class SL_CLASS = ServiceLifecycle.class; // Component & ServiceManager references private final Object m_object; private final ServiceManager m_manager; /** * Simple constructor, sets all internal references * * @param object a Component instance * @param manager a ServiceManager instance */ public Handler(final Object object, final ServiceManager manager) { m_object = object; m_manager = manager; } /** * invoke method, handles all method invocations for this * particular proxy. * *

* Usually the invocation is passed through to the * actual component the proxy wraps, unless the method belongs to * the ServiceLifecycle interface where it is handled * locally. *

* * @param proxy the Proxy instance the method was invoked on * @param method the invoked method Method object * @param args an Object[] array of arguments * @return an Object value or null if none * @exception Throwable if an error occurs */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // if ServiceLifecycle.destroy() called, return to CM if (method.getDeclaringClass().equals(SL_CLASS)) { if (method.getName().equals(SL_DESTROY)) { m_manager.release(m_object); } return null; } // otherwise pass call to the real object return method.invoke(m_object, args); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy