View Javadoc
1 package org.codehaus.ivory.provider; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.InvocationTargetException; 5 import java.lang.reflect.Method; 6 import java.lang.reflect.Proxy; 7 8 import javax.xml.rpc.server.ServiceLifecycle; 9 10 import org.apache.avalon.framework.service.ServiceManager; 11 import org.apache.axis.AxisFault; 12 import org.apache.axis.MessageContext; 13 import org.apache.axis.handlers.soap.SOAPService; 14 15 /*** 16 * 17 * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a> 18 * @since May 23, 2003 19 */ 20 public class IvoryAvalonProvider 21 extends IvoryProvider 22 { 23 /*** 24 * Constant used to retrieve the ServiceManager reference 25 * from the MessageContext object. 26 */ 27 public static final String SERVICE_MANAGER = "service-manager"; 28 29 /*** 30 * Constant which represents the name of the ROLE this 31 * provider should <i>lookup</i> to service a request with. This is 32 * specified in the <parameter name="" value=""/> part of the 33 * deployment xml. 34 */ 35 public static final String ROLE = "role"; 36 37 /*** 38 * Returns the service object. 39 * 40 * @param msgContext the message context 41 * @param role the Avalon ROLE to lookup to find the service object implementation 42 * @return an object that implements the service 43 * @exception Exception if an error occurs 44 */ 45 protected Object makeNewServiceObject( 46 MessageContext msgContext, 47 String role) 48 throws Exception 49 { 50 ServiceManager manager = 51 (ServiceManager) msgContext 52 .getAxisEngine() 53 .getApplicationSession() 54 .get( SERVICE_MANAGER ); 55 56 if (manager == null) 57 throw new AxisFault("Could not access Avalon ServiceManager"); 58 59 return decorate(manager.lookup(role), manager); 60 } 61 62 /*** 63 * Helper method for decorating a <code>Component</code> with a Handler 64 * proxy (see below). 65 * 66 * @param object a <code>Component</code> instance 67 * @param manager a <code>ComponentManager</code> instance 68 * @return the <code>Proxy</code> wrapped <code>Component</code> instance 69 * @exception Exception if an error occurs 70 */ 71 private Object decorate(final Object object, final ServiceManager manager) 72 throws Exception 73 { 74 // obtain a list of all interfaces this object implements 75 Class[] interfaces = object.getClass().getInterfaces(); 76 77 // add ServiceLifecycle to it 78 Class[] adjusted = new Class[interfaces.length + 1]; 79 System.arraycopy(interfaces, 0, adjusted, 0, interfaces.length); 80 adjusted[interfaces.length] = ServiceLifecycle.class; 81 82 // create a proxy implementing those interfaces 83 Object proxy = 84 Proxy.newProxyInstance( 85 this.getClass().getClassLoader(), 86 adjusted, 87 new Handler(object, manager)); 88 89 // return the proxy 90 return proxy; 91 } 92 93 /*** 94 * Get the service class description 95 * 96 * @param role the Avalon ROLE name 97 * @param service a <code>SOAPService</code> instance 98 * @param msgContext the message context 99 * @return service class description 100 * @exception AxisFault if an error occurs 101 */ 102 protected Class getServiceClass( 103 String role, 104 SOAPService service, 105 MessageContext msgContext) 106 throws AxisFault 107 { 108 // Assuming ExcaliburComponentManager semantics the ROLE name is 109 // actually the class name, potentially with a variant following 110 // the class name with a '/' separator 111 112 int i; 113 114 if ((i = role.indexOf('/')) != -1) 115 { 116 return super.getServiceClass( role.substring(0, i), service, msgContext ); 117 } 118 else 119 { 120 return super.getServiceClass( role, service, msgContext ); 121 } 122 123 } 124 125 /*** 126 * <code>InvocationHandler</code> class for managing Avalon 127 * <code>Components</code>. 128 * 129 * <p> 130 * Components retrieved from an Avalon ComponentManager must be 131 * returned to the manager when they are no longer required. 132 * </p> 133 * 134 * <p> 135 * The returning of Components to their ComponentManager is handled 136 * by a Proxy class which uses the following InvocationHandler. 137 * </p> 138 * 139 * <p> 140 * Each Component returned by this Provider is wrapped inside a 141 * Proxy class which implements all of the Component's interfaces 142 * including javax.xml.rpc.server.ServiceLifecycle. 143 * </p> 144 * 145 * <p> 146 * When Axis is finished with the object returned by this provider, 147 * it invokes ServiceLifecycle.destroy(). This is intercepted by the 148 * InvocationHandler and the Component is returned at this time back 149 * to the ComponentManager it was retrieved from. 150 * </p> 151 * 152 * <p> 153 * <b>Note</b>, when Axis invokes ServiceLifecycle.destroy() is dependant 154 * on the scope of the service (ie. Request, Session & Application). 155 * </p> 156 */ 157 final class Handler implements InvocationHandler 158 { 159 // Constants describing the ServiceLifecycle.destroy method 160 private final String SL_DESTROY = "destroy"; 161 private final Class SL_CLASS = ServiceLifecycle.class; 162 163 // Component & ServiceManager references 164 private final Object m_object; 165 private final ServiceManager m_manager; 166 167 /*** 168 * Simple constructor, sets all internal references 169 * 170 * @param object a <code>Component</code> instance 171 * @param manager a <code>ComponentManager</code> instance 172 * @param log a <code>Logger</code> instance 173 */ 174 public Handler(final Object object, final ServiceManager manager) 175 { 176 m_object = object; 177 m_manager = manager; 178 } 179 180 /*** 181 * <code>invoke</code> method, handles all method invocations for this 182 * particular proxy. 183 * 184 * <p> 185 * Usually the invocation is passed through to the 186 * actual component the proxy wraps, unless the method belongs to 187 * the <code>ServiceLifecycle</code> interface where it is handled 188 * locally. 189 * </p> 190 * 191 * @param proxy the <code>Proxy</code> instance the method was invoked on 192 * @param method the invoked method <code>Method</code> object 193 * @param args an <code>Object[]</code> array of arguments 194 * @return an <code>Object</code> value or null if none 195 * @exception Throwable if an error occurs 196 */ 197 public Object invoke(Object proxy, Method method, Object[] args) 198 throws Throwable 199 { 200 try 201 { 202 // if ServiceLifecycle.destroy() called, return to CM 203 if (method.getDeclaringClass().equals(SL_CLASS)) 204 { 205 if (method.getName().equals(SL_DESTROY)) 206 { 207 m_manager.release(m_object); 208 } 209 210 return null; 211 } 212 else // otherwise pass call to the real object 213 { 214 return method.invoke(m_object, args); 215 } 216 } 217 catch ( InvocationTargetException e ) 218 { 219 throw e.getTargetException(); 220 } 221 } 222 } 223 }

This page was automatically generated by Maven