1 22 23 package org.jboss.resource.binding.remote; 24 25 import java.io.ByteArrayOutputStream ; 26 import java.io.IOException ; 27 import java.io.ObjectOutputStream ; 28 import java.io.Serializable ; 29 import java.lang.reflect.Method ; 30 import java.util.ArrayList ; 31 import java.util.HashMap ; 32 import java.util.Map ; 33 34 import javax.management.ObjectName ; 35 import javax.naming.BinaryRefAddr ; 36 import javax.naming.InitialContext ; 37 import javax.naming.NamingException ; 38 import javax.naming.Reference ; 39 import javax.naming.StringRefAddr ; 40 import javax.resource.Referenceable ; 41 42 import org.jboss.deployment.DeploymentException; 43 import org.jboss.invocation.Invocation; 44 import org.jboss.invocation.Invoker; 45 import org.jboss.invocation.InvokerInterceptor; 46 import org.jboss.invocation.MarshalledInvocation; 47 import org.jboss.logging.Logger; 48 import org.jboss.proxy.ClientMethodInterceptor; 49 import org.jboss.proxy.GenericProxyFactory; 50 import org.jboss.resource.adapter.jdbc.remote.DataSourceFactory; 51 import org.jboss.resource.connectionmanager.ConnectionFactoryBindingService; 52 import org.jboss.system.Registry; 53 import org.jboss.util.naming.NonSerializableFactory; 54 import org.jboss.util.naming.Util; 55 56 62 public class RemoteConnectionFactoryService extends ConnectionFactoryBindingService implements RemoteConnectionFactoryServiceMBean 63 { 64 66 67 private static Logger log = Logger.getLogger(RemoteConnectionFactoryService.class); 68 69 70 private ObjectName jmxInvokerName; 71 72 73 private Invoker delegateInvoker; 74 75 76 private Object theProxy; 77 78 79 private Map marshalledInvocationMapping = new HashMap (); 80 81 82 private Map objectMap = new HashMap (); 83 84 public ObjectName getJMXInvokerName() 85 { 86 return jmxInvokerName; 87 } 88 89 public void setJMXInvokerName(ObjectName jmxInvokerName) 90 { 91 this.jmxInvokerName = jmxInvokerName; 92 } 93 94 protected void startService() throws Exception 95 { 96 determineBindName(); 97 createConnectionFactory(); 98 99 if(jmxInvokerName != null){ 100 101 createProxy(); 102 calculateHashes(); 103 bindConnectionFactory(); 104 105 }else{ 106 107 super.bindConnectionFactory(); 108 } 109 110 } 111 112 public Object invoke(Invocation invocation) throws Exception 113 { 114 Object result = null; 115 116 if(invocation instanceof MarshalledInvocation){ 117 118 MarshalledInvocation mi = (MarshalledInvocation)invocation; 119 mi.setMethodMap(marshalledInvocationMapping); 120 } 121 122 final Method targetMethod = invocation.getMethod(); 123 final Class targetClass = targetMethod.getDeclaringClass(); 124 final Object [] targetArguments = invocation.getArguments(); 125 126 final Object retVal = internalInvoke(targetClass, targetMethod, targetArguments, invocation.getId()); 127 128 if(!(retVal instanceof Serializable ) && retVal != null){ 129 130 log.debug("Creating proxy for instance " + retVal); 131 result = createProxy(retVal); 132 133 } 134 135 return result; 136 } 137 138 private Object internalInvoke(final Class clazz, final Method method, final Object [] arguments, final Object id) 139 throws Exception 140 { 141 142 Object result = null; 143 144 if (clazz.isAssignableFrom(cf.getClass())) 147 { 148 149 InitialContext initCtx = new InitialContext (); 150 Object boundCf = initCtx.lookup(bindName); 151 result = method.invoke(boundCf, arguments); 152 153 154 objectMap.put(Integer.valueOf(String.valueOf(result.hashCode())), result); 155 156 } 157 else 158 { 159 160 Object target = objectMap.get(id); 161 162 if (target != null) 163 { 164 165 result = method.invoke(target, arguments); 166 167 if (method.getName().equals("close")) 169 { 170 objectMap.remove(id); 171 } 172 173 } 174 175 } 176 177 return result; 178 179 } 180 181 private void calculateHashes(Class clazz){ 182 183 Class [] interfaces = clazz.getInterfaces(); 184 185 for (int i = 0; i < interfaces.length; i++) 186 { 187 Class target = interfaces[i]; 188 Map m = MarshalledInvocation.methodToHashesMap(target); 189 marshalledInvocationMapping.putAll(m); 190 191 } 192 } 193 194 private void calculateHashes(){ 195 196 Class [] cfInterfaces = cf.getClass().getInterfaces(); 197 198 for (int i = 0; i < cfInterfaces.length; i++) 199 { 200 Class clazz = cfInterfaces[i]; 201 Method [] methods = clazz.getMethods(); 202 203 for (int j = 0; j < methods.length; j++) 204 { 205 206 Method m = methods[j]; 207 Long hash = new Long (MarshalledInvocation.calculateHash(m)); 208 marshalledInvocationMapping.put(hash, m); 209 210 } 211 } 212 } 213 214 private Object createProxy(Object value) throws Exception { 215 216 delegateInvoker = (Invoker)Registry.lookup(jmxInvokerName); 217 log.debug("Using delegate: " + delegateInvoker + " for invoker=" + jmxInvokerName); 218 219 calculateHashes(value.getClass()); 221 222 final Class [] targetInterfaces = value.getClass().getInterfaces(); 223 final ArrayList interceptorList = new ArrayList (); 224 Object cacheID = new Integer (value.hashCode()); 225 String proxyBindingName = null; 226 String jndiName = null; 227 228 interceptorList.add(ClientMethodInterceptor.class); 229 interceptorList.add(InvokerInterceptor.class); 230 231 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 232 GenericProxyFactory proxyFactory = new GenericProxyFactory(); 233 234 Object proxy = proxyFactory.createProxy(cacheID, serviceName, 235 delegateInvoker, jndiName, proxyBindingName, interceptorList, 236 loader, targetInterfaces); 237 238 objectMap.put(cacheID, value); 239 240 return proxy; 241 242 } 243 244 private void createProxy() throws Exception { 245 246 delegateInvoker = (Invoker)Registry.lookup(jmxInvokerName); 247 log.debug("Using delegate: " + delegateInvoker + " for invoker=" + jmxInvokerName); 248 249 final ObjectName serviceName = getServiceName(); 250 final Integer nameHash = Integer.valueOf(String.valueOf(serviceName.hashCode())); 251 Registry.bind(nameHash, serviceName); 252 253 Object cacheID = null; 254 String proxyBindingName = null; 255 String jndiName = null; 256 257 final Class [] connectionFactoryInterface = cf.getClass().getInterfaces(); 258 final ArrayList interceptorList = new ArrayList (); 259 interceptorList.add(ClientMethodInterceptor.class); 260 interceptorList.add(InvokerInterceptor.class); 261 262 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 263 GenericProxyFactory proxyFactory = new GenericProxyFactory(); 264 theProxy = proxyFactory.createProxy(cacheID, serviceName, 265 delegateInvoker, jndiName, proxyBindingName, interceptorList, 266 loader, connectionFactoryInterface); 267 268 } 269 270 protected void bindConnectionFactory() throws Exception 271 { 272 InitialContext initCtx = new InitialContext (); 273 274 try 275 { 276 277 NonSerializableFactory.rebind(bindName, cf); 278 final Referenceable referenceable = (Referenceable ) cf; 279 280 final ByteArrayOutputStream baos = new ByteArrayOutputStream (); 281 final ObjectOutputStream oos = new ObjectOutputStream (baos); 282 oos.writeObject(theProxy); 283 oos.close(); 284 285 final byte[] proxyBytes = baos.toByteArray(); 286 final BinaryRefAddr dsAddr = new BinaryRefAddr ("ProxyData", proxyBytes); 287 final String remoteFactoryName = RemoteConnectionFactoryHelper.class.getName(); 288 final String localFactoryName = cf.getClass().getName(); 289 290 final Reference dsRef = new Reference (localFactoryName, dsAddr, remoteFactoryName, null); 291 referenceable.setReference(dsRef); 292 293 baos.reset(); 294 final ObjectOutputStream oos2 = new ObjectOutputStream (baos); 295 oos2.writeObject(RemoteConnectionFactoryHelper.vmID); 296 oos2.close(); 297 final byte[] id = baos.toByteArray(); 298 final BinaryRefAddr localAddr = new BinaryRefAddr ("VMID", id); 299 dsRef.add(localAddr); 300 301 final StringRefAddr jndiRef = new StringRefAddr ("JndiName", bindName); 302 dsRef.add(jndiRef); 303 Util.rebind(initCtx, bindName, cf); 304 305 log.info("Bound ConnectionManager '" + serviceName + "' to JNDI name '" + bindName + "'"); 306 } 307 catch (NamingException e) 308 { 309 log.error("Could not bind ConnectionFactory into jndi: " + bindName, e); 310 throw new DeploymentException("Could not bind ConnectionFactory into jndi: " + bindName, e); 311 312 } 313 finally 314 { 315 316 if (initCtx != null) 317 { 318 319 initCtx.close(); 320 321 } 322 323 } 324 325 } 326 327 328 } 329 | Popular Tags |