diff options
Diffstat (limited to 'sca-java-1.x/tags/0.91-incubating/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBHandler.java')
-rw-r--r-- | sca-java-1.x/tags/0.91-incubating/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBHandler.java | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/sca-java-1.x/tags/0.91-incubating/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBHandler.java b/sca-java-1.x/tags/0.91-incubating/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBHandler.java new file mode 100644 index 0000000000..8d0d309aef --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/binding-ejb/src/main/java/org/apache/tuscany/sca/binding/ejb/util/EJBHandler.java @@ -0,0 +1,420 @@ +/* + * 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.tuscany.sca.binding.ejb.util; + +import java.io.Externalizable; +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.rmi.RemoteException; +import java.rmi.UnexpectedException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.HashMap; +import java.util.Map; + +import javax.ejb.EJBObject; +import javax.rmi.CORBA.Util; + +import org.apache.tuscany.sca.binding.ejb.java2idl.ExceptionType; +import org.apache.tuscany.sca.binding.ejb.java2idl.Java2IDLUtil; +import org.omg.CORBA.ORB; +import org.omg.CORBA.SystemException; +import org.omg.CORBA.portable.ApplicationException; +import org.omg.CORBA.portable.ObjectImpl; +import org.omg.CORBA.portable.RemarshalException; +import org.omg.CORBA.portable.ServantObject; +import org.omg.CORBA_2_3.portable.InputStream; +import org.omg.CORBA_2_3.portable.OutputStream; +import org.osoa.sca.ServiceRuntimeException; + +/** + * EJBMessageHandler + */ +public class EJBHandler { + private Object ejbStub; + + private InterfaceInfo interfaceInfo; + private Class ejbInterface; + + public EJBHandler(NamingEndpoint namingEndpoint, Class ejbInterface) { + this(namingEndpoint, InterfaceInfo.getInstance(ejbInterface)); + this.ejbInterface = ejbInterface; + } + + // locates the stub + public EJBHandler(NamingEndpoint namingEndpoint, InterfaceInfo ejbInterface) { + try { + this.ejbStub = EJBStubHelper.lookup(namingEndpoint); + this.interfaceInfo = ejbInterface; + } catch (Exception e) { + Throwable b = e.getCause(); + b.printStackTrace(); + throw new ServiceRuntimeException(e); + } + } + + private final static Map<String, Class> primitiveClasses = new HashMap<String, Class>(); + static { + primitiveClasses.put("boolean", boolean.class); + primitiveClasses.put("byte", byte.class); + primitiveClasses.put("char", char.class); + primitiveClasses.put("short", short.class); + primitiveClasses.put("int", int.class); + primitiveClasses.put("long", long.class); + primitiveClasses.put("float", float.class); + primitiveClasses.put("double", double.class); + primitiveClasses.put("void", void.class); + } + + private static Class loadClass(final String name) { + Class type = (Class)primitiveClasses.get(name); + if (type != null) + return type; + return (Class)AccessController.doPrivileged(new PrivilegedAction<Class>() { + public Class run() { + try { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + return Class.forName(name, true, classLoader); + } catch (ClassNotFoundException e) { + return null; + } + } + }); + } + + // invokes EJB method + public Object invoke(String methodName, Object[] args) { + Object response = null; + try { + if (ejbStub instanceof ObjectImpl) { + ObjectImpl objectImpl = (ObjectImpl)ejbStub; + // TODO: If the Java 2 security is turned on, then + // the ORB will try to create proxy + // from the interfaces defined on the stub + if (System.getSecurityManager() == null && objectImpl._is_local()) { + /* + * CORBA.Stub is what the object from JNDI will be for a + * remote EJB in the same JVM as the client, but with no + * stub classes available on the client + */ + response = invokeLocalCORBACall(objectImpl, methodName, args); + } else { + /* + * _EJBObject_Stub is what the object from JNDI will be for + * a remote EJB with no stub classes available on the client + */ + response = invokeRemoteCORBACall(objectImpl, methodName, args); + } + } else { + /* + * A generated ejb stub or it must be an EJB in the same ear as + * the client or an AppServer with a single classloader, so + * reflection can be used directly on the JNDI + */ + JavaReflectionAdapter reflectionAdapter = + JavaReflectionAdapter.createJavaReflectionAdapter(ejbStub.getClass()); + try { + Method method = reflectionAdapter.getMethod(methodName); + response = method.invoke(ejbStub, args); + } catch (InvocationTargetException e) { + Throwable t = e.getTargetException(); + // FIXME need to throw really a business exception. + // ServiceBusinessException? + // Tuscany core doesn't have ServiceBusinessException + throw new ServiceRuntimeException(t); + } + } + + return response; + } catch (Exception e) { + // FIXME this be business exception? Tuscany core doesn't have + // ServiceBusinessException + throw new ServiceRuntimeException(e); + + } catch (Throwable e) { + throw new ServiceRuntimeException(e); + } + } + + /** + * Get the IDL operation name for a java method + * + * @param methodName java method name + * @return The IDL operation name + */ + private String getOperation(String methodName) { + if (interfaceInfo == null) + return methodName; + MethodInfo methodInfo = interfaceInfo.getMethod(methodName); + if (methodInfo != null) + return methodInfo.getIDLName(); + else + return null; + } + + /* + * Derive the EJB interface name from the Stub When loading a stub class + * corresponding to an interface or class <packagename>.<typename>, the + * class <packagename>._<typename>_Stub shall be used if it exists; + * otherwise, the class org.omg.stub.<packagename>._<typename>_Stub shall + * be used. + */ + private static String getInterface(String stubName) { + int index = stubName.lastIndexOf('.'); + String packageName = null; + String typeName = stubName; + if (index != -1) { + packageName = stubName.substring(0, index); + if (packageName.startsWith("org.omg.stub.")) { + packageName = packageName.substring("org.omg.stub.".length()); + } + typeName = stubName.substring(index + 1); + } + if (typeName.startsWith("_") && typeName.endsWith("_Stub")) { + typeName = typeName.substring(1, typeName.length() - "_Stub".length()); + } + if (packageName != null) + return packageName + "." + typeName; + else + return typeName; + } + + /** + * Invoke a method on the local CORBA object + * + * @param stub + * @param methodName + * @param args + * @return + * @throws RemoteException + * @throws ServiceBusinessException + */ + protected Object invokeLocalCORBACall(final ObjectImpl stub, String methodName, Object[] args) + throws RemoteException { + + final String operation = getOperation(methodName); + + Class type = loadClass(getInterface(stub.getClass().getName())); + if (type == null) + type = (ejbInterface != null) ? ejbInterface : EJBObject.class; + + ServantObject so = stub._servant_preinvoke(operation, type); + if (so == null) { + // The Servant is not local any more + return invokeRemoteCORBACall(stub, methodName, args); + } + Object[] newArgs = null; + ORB orb = stub._orb(); + try { + if (args != null) + newArgs = Util.copyObjects(args, orb); + JavaReflectionAdapter reflectionAdapter = + JavaReflectionAdapter.createJavaReflectionAdapter(so.servant.getClass()); + Method method = reflectionAdapter.getMethod(methodName); + Object obj = reflectionAdapter.invoke(method, so.servant, newArgs); + Object result = Util.copyObject(obj, orb); + return result; + + } catch (InvocationTargetException e) { + Throwable exCopy = (Throwable)Util.copyObject(e.getTargetException(), orb); + MethodInfo methodInfo = interfaceInfo.getMethod(methodName); + String[] exceptionTypes = methodInfo.getExceptionTypes(); + for (int i = 0; i < exceptionTypes.length; i++) { + Class exceptionType = loadClass(exceptionTypes[i]); + if (exceptionType.isAssignableFrom(exCopy.getClass())) + throw new ServiceRuntimeException(exCopy); // FIXME should + // be business + // exception? + } + throw Util.wrapException(exCopy); + } catch (Throwable e) { + // Other exceptions thrown from "invoke" + throw new ServiceRuntimeException(e); + } finally { + stub._servant_postinvoke(so); + } + } + + /** + * Invoke a method on a remote CORBA object + * + * @param stub The remote stub + * @param methodName The name of the method + * @param args Argument list + * @return + * @throws RemoteException + * @throws ServiceBusinessException + */ + protected Object invokeRemoteCORBACall(ObjectImpl stub, String methodName, Object[] args) throws RemoteException { + + try { + String operation = getOperation(methodName); + + MethodInfo methodInfo = interfaceInfo.getMethod(methodName); + if (methodInfo == null) { + throw new ServiceRuntimeException("Invalid Method " + methodName); + } + String[] types = methodInfo.getParameterTypes(); + if (args != null) { + if (types.length != args.length) + throw new ServiceRuntimeException( + "The argument list doesn't match the method signature of " + methodName); + } + + Class[] parameterTypes = new Class[types.length]; + for (int i = 0; i < types.length; i++) { + parameterTypes[i] = loadClass(types[i]); + } + Class returnType = loadClass(methodInfo.getReturnType()); + + InputStream in = null; + try { + OutputStream out = (OutputStream)stub._request(operation, true); + + for (int i = 0; i < types.length; i++) { + // Object arg = (args.length < i) ? null : args[i]; + writeValue(out, args[i], parameterTypes[i]); + } + if (returnType == void.class) { + // void return + stub._invoke(out); + return null; + } else { + // read the return value + in = (InputStream)stub._invoke(out); + Object response = readValue(in, returnType); + return response; + } + + } catch (ApplicationException ex) { + in = (InputStream)ex.getInputStream(); + String id = in.read_string(); + // Check if the id matches to any declared exceptions for the + // method + String[] exceptionTypes = methodInfo.getExceptionTypes(); + for (int i = 0; i < exceptionTypes.length; i++) { + Class exceptionType = loadClass(exceptionTypes[i]); + String exceptionId = ExceptionType.getExceptionType(exceptionType).getExceptionRepositoryId(); + if (id.equals(exceptionId)) { + Throwable t = (Throwable)in.read_value(exceptionType); + throw new ServiceRuntimeException(t); // FIXME should + // be + // ServcieBusinessException? + // no support by + // Tuscany core + // for + // ServcieBusinessException. + } + } + throw new UnexpectedException(id); + } catch (RemarshalException ex) { + return invokeRemoteCORBACall(stub, methodName, args); + } finally { + stub._releaseReply(in); + } + } catch (SystemException ex) { + throw Util.mapSystemException(ex); + } + } + + /** + * @param out + * @param value + * @param type + */ + protected void writeValue(OutputStream out, Object value, Class type) { + if (type == null) + out.write_value((Serializable)value); + else if (type == Object.class || type == Serializable.class || type == Externalizable.class) { + // Any + Util.writeAny(out, value); + } else if (type == Integer.TYPE) { + // java int maps to CORBA long + out.write_long(((Integer)value).intValue()); + } else if (type == Short.TYPE) { + out.write_short(((Short)value).shortValue()); + } else if (type == Boolean.TYPE) { + out.write_boolean(((Boolean)value).booleanValue()); + } else if (type == Byte.TYPE) { + out.write_octet(((Byte)value).byteValue()); + } else if (type == Long.TYPE) { + out.write_longlong(((Long)value).longValue()); + } else if (type == Double.TYPE) { + out.write_double(((Double)value).doubleValue()); + } else if (type == Float.TYPE) { + out.write_float(((Float)value).floatValue()); + } else if (type == Character.TYPE) { + out.write_wchar(((Character)value).charValue()); + } else if (type.isArray()) { + out.write_value((Serializable)value, type); + } else if (Java2IDLUtil.isRemoteInterface(type)) { + // Remote interface + Util.writeRemoteObject(out, value); + } else if (Java2IDLUtil.isAbstractInterface(type)) { + // Non-remote Interface + Util.writeAbstractObject(out, value); + } else { + out.write_value((Serializable)value, type); + } + } + + /** + * @param in + * @param type + * @return + */ + protected Object readValue(InputStream in, Class type) { + Object value = null; + if (type == null) + value = in.read_value(); + else if (type == Object.class || type == Serializable.class || type == Externalizable.class) { + value = Util.readAny(in); + } else if (type == Integer.TYPE) { + value = new Integer(in.read_long()); + } else if (type == Short.TYPE) { + value = new Short(in.read_short()); + } else if (type == Boolean.TYPE) { + value = new Boolean(in.read_boolean()); + } else if (type == Byte.TYPE) { + value = new Byte(in.read_octet()); + } else if (type == Long.TYPE) { + value = new Long(in.read_longlong()); + } else if (type == Float.TYPE) { + value = new Float(in.read_float()); + } else if (type == Double.TYPE) { + value = new Double(in.read_double()); + } else if (type == Character.TYPE) { + value = new Character(in.read_wchar()); + } else if (type.isArray()) { + // [] + value = in.read_value(type); + } else if (Java2IDLUtil.isRemoteInterface(type)) { + // java.rmi.Remote + value = in.read_Object(type); + } else if (Java2IDLUtil.isAbstractInterface(type)) { + // Non-remote Interface + value = in.read_abstract_interface(type); + } else { + // java.io.Serializable + value = in.read_value(type); + } + return value; + } +} |