View Javadoc
1 /* 2 * The Apache Software License, Version 1.1 3 * 4 * 5 * Copyright (c) 2001 The Apache Software Foundation. All rights 6 * reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. The end-user documentation included with the redistribution, 21 * if any, must include the following acknowledgment: 22 * "This product includes software developed by the 23 * Apache Software Foundation (http://www.apache.org/)." 24 * Alternately, this acknowledgment may appear in the software itself, 25 * if and wherever such third-party acknowledgments normally appear. 26 * 27 * 4. The names "Axis" and "Apache Software Foundation" must 28 * not be used to endorse or promote products derived from this 29 * software without prior written permission. For written 30 * permission, please contact apache@apache.org. 31 * 32 * 5. Products derived from this software may not be called "Apache", 33 * nor may "Apache" appear in their name, without prior written 34 * permission of the Apache Software Foundation. 35 * 36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 39 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 42 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 43 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 44 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 45 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 46 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 47 * SUCH DAMAGE. 48 * ==================================================================== 49 * 50 * This software consists of voluntary contributions made by many 51 * individuals on behalf of the Apache Software Foundation. For more 52 * information on the Apache Software Foundation, please see 53 * <http://www.apache.org/>. 54 */ 55 56 package org.codehaus.ivory.provider; 57 58 import java.lang.reflect.InvocationHandler; 59 import java.lang.reflect.InvocationTargetException; 60 import java.lang.reflect.Method; 61 import java.lang.reflect.Proxy; 62 63 import javax.xml.rpc.server.ServiceLifecycle; 64 65 import org.apache.avalon.framework.service.ServiceManager; 66 import org.apache.axis.AxisFault; 67 import org.apache.axis.MessageContext; 68 import org.apache.axis.handlers.soap.SOAPService; 69 import org.apache.axis.providers.java.RPCProvider; 70 71 /*** 72 * Provider class which allows you to specify an Avalon <b>ROLE</b> for 73 * servicing Axis SOAP requests. 74 * 75 * <p> 76 * The specified <b>ROLE</b> corresponds to a particular implementation 77 * which is retrieved by a given Avalon <code>ComponentManager</code>. 78 * For more information about Avalon, see the Avalon. 79 * <a href="http://jakarta.apache.org/avalon">website</a>. 80 * </p> 81 * 82 * <p> 83 * To use this class, you need to add your Avalon <code>ComponentManager</code> 84 * instance to the <code>MessageContext</code> that is Axis uses to process 85 * messages with. 86 * </p> 87 * 88 * <p> 89 * To do this you could for example subclass the AxisServlet and override the 90 * <code>createMessageContext()</code> method adding the ComponentManager, eg: 91 * 92 * <pre> 93 * protected MessageContext createMessageContext(...) 94 * { 95 * MessageContext context = super.createMessageContext(); 96 * context.setProperty(AvalonProvider.COMPONENT_MANAGER, m_manager); 97 * return context; 98 * } 99 * </pre> 100 * 101 * and appropriately add the AvalonProvider to the list of handlers in your 102 * server-config.wsdd (suggestions on how to improve this are welcomed) 103 * </p> 104 * 105 * <p> 106 * This provider will use that <code>ComponentManager</code> reference to 107 * retrieve objects. 108 * </p> 109 * 110 * <p> 111 * In your deployment descriptor use the following syntax: 112 * 113 * <pre> 114 * <service name="myservice" provider="java:Avalon"> 115 * <parameter name="role" value="my.avalon.role.name"/> 116 * <parameter name="className" value="my.avalon.roles.interface.name"/> 117 * <parameter name="allowedMethods" value="allowed.methods"/> 118 * </service> 119 * </pre> 120 * 121 * </p> 122 * 123 * @author <a href="mailto:crafterm@apache.org">Marcus Crafter</a> 124 * @revision CVS $Id: AvalonProvider.java,v 1.1 2003/07/02 21:29:30 dandiep Exp $ 125 */ 126 public class AvalonProvider 127 extends RPCProvider 128 { 129 /*** 130 * Constant used to retrieve the ServiceManager reference 131 * from the MessageContext object. 132 */ 133 public static final String SERVICE_MANAGER = "service-manager"; 134 135 /*** 136 * Constant which represents the name of the ROLE this 137 * provider should <i>lookup</i> to service a request with. This is 138 * specified in the <parameter name="" value=""/> part of the 139 * deployment xml. 140 */ 141 public static final String ROLE = "role"; 142 143 /*** 144 * Returns the service object. 145 * 146 * @param msgContext the message context 147 * @param role the Avalon ROLE to lookup to find the service object implementation 148 * @return an object that implements the service 149 * @exception Exception if an error occurs 150 */ 151 protected Object makeNewServiceObject( 152 MessageContext msgContext, 153 String role) 154 throws Exception 155 { 156 ServiceManager manager = 157 (ServiceManager) msgContext 158 .getAxisEngine() 159 .getApplicationSession() 160 .get( SERVICE_MANAGER ); 161 162 if (manager == null) 163 throw new AxisFault("Could not access Avalon ServiceManager"); 164 165 return decorate(manager.lookup(role), manager); 166 } 167 168 /*** 169 * Helper method for decorating a <code>Component</code> with a Handler 170 * proxy (see below). 171 * 172 * @param object a <code>Component</code> instance 173 * @param manager a <code>ComponentManager</code> instance 174 * @return the <code>Proxy</code> wrapped <code>Component</code> instance 175 * @exception Exception if an error occurs 176 */ 177 private Object decorate(final Object object, final ServiceManager manager) 178 throws Exception 179 { 180 // obtain a list of all interfaces this object implements 181 Class[] interfaces = object.getClass().getInterfaces(); 182 183 // add ServiceLifecycle to it 184 Class[] adjusted = new Class[interfaces.length + 1]; 185 System.arraycopy(interfaces, 0, adjusted, 0, interfaces.length); 186 adjusted[interfaces.length] = ServiceLifecycle.class; 187 188 // create a proxy implementing those interfaces 189 Object proxy = 190 Proxy.newProxyInstance( 191 this.getClass().getClassLoader(), 192 adjusted, 193 new Handler(object, manager)); 194 195 // return the proxy 196 return proxy; 197 } 198 199 /*** 200 * Get the service class description 201 * 202 * @param role the Avalon ROLE name 203 * @param service a <code>SOAPService</code> instance 204 * @param msgContext the message context 205 * @return service class description 206 * @exception AxisFault if an error occurs 207 */ 208 protected Class getServiceClass( 209 String role, 210 SOAPService service, 211 MessageContext msgContext) 212 throws AxisFault 213 { 214 // Assuming ExcaliburComponentManager semantics the ROLE name is 215 // actually the class name, potentially with a variant following 216 // the class name with a '/' separator 217 218 int i; 219 220 if ((i = role.indexOf('/')) != -1) 221 { 222 return super.getServiceClass( role.substring(0, i), service, msgContext ); 223 } 224 else 225 { 226 return super.getServiceClass( role, service, msgContext ); 227 } 228 229 } 230 231 /*** 232 * <code>InvocationHandler</code> class for managing Avalon 233 * <code>Components</code>. 234 * 235 * <p> 236 * Components retrieved from an Avalon ComponentManager must be 237 * returned to the manager when they are no longer required. 238 * </p> 239 * 240 * <p> 241 * The returning of Components to their ComponentManager is handled 242 * by a Proxy class which uses the following InvocationHandler. 243 * </p> 244 * 245 * <p> 246 * Each Component returned by this Provider is wrapped inside a 247 * Proxy class which implements all of the Component's interfaces 248 * including javax.xml.rpc.server.ServiceLifecycle. 249 * </p> 250 * 251 * <p> 252 * When Axis is finished with the object returned by this provider, 253 * it invokes ServiceLifecycle.destroy(). This is intercepted by the 254 * InvocationHandler and the Component is returned at this time back 255 * to the ComponentManager it was retrieved from. 256 * </p> 257 * 258 * <p> 259 * <b>Note</b>, when Axis invokes ServiceLifecycle.destroy() is dependant 260 * on the scope of the service (ie. Request, Session & Application). 261 * </p> 262 */ 263 final class Handler implements InvocationHandler 264 { 265 // Constants describing the ServiceLifecycle.destroy method 266 private final String SL_DESTROY = "destroy"; 267 private final Class SL_CLASS = ServiceLifecycle.class; 268 269 // Component & ServiceManager references 270 private final Object m_object; 271 private final ServiceManager m_manager; 272 273 /*** 274 * Simple constructor, sets all internal references 275 * 276 * @param object a <code>Component</code> instance 277 * @param manager a <code>ComponentManager</code> instance 278 * @param log a <code>Logger</code> instance 279 */ 280 public Handler(final Object object, final ServiceManager manager) 281 { 282 m_object = object; 283 m_manager = manager; 284 } 285 286 /*** 287 * <code>invoke</code> method, handles all method invocations for this 288 * particular proxy. 289 * 290 * <p> 291 * Usually the invocation is passed through to the 292 * actual component the proxy wraps, unless the method belongs to 293 * the <code>ServiceLifecycle</code> interface where it is handled 294 * locally. 295 * </p> 296 * 297 * @param proxy the <code>Proxy</code> instance the method was invoked on 298 * @param method the invoked method <code>Method</code> object 299 * @param args an <code>Object[]</code> array of arguments 300 * @return an <code>Object</code> value or null if none 301 * @exception Throwable if an error occurs 302 */ 303 public Object invoke(Object proxy, Method method, Object[] args) 304 throws Throwable 305 { 306 try 307 { 308 // if ServiceLifecycle.destroy() called, return to CM 309 if (method.getDeclaringClass().equals(SL_CLASS)) 310 { 311 if (method.getName().equals(SL_DESTROY)) 312 { 313 m_manager.release(m_object); 314 } 315 316 return null; 317 } 318 else // otherwise pass call to the real object 319 { 320 return method.invoke(m_object, args); 321 } 322 } 323 catch ( InvocationTargetException e ) 324 { 325 throw e.getTargetException(); 326 } 327 } 328 } 329 }

This page was automatically generated by Maven