| Method from org.apache.openejb.core.ivm.BaseEjbProxyHandler Detail: |
abstract protected Object _invoke(Object proxy,
Class interfce,
Method method,
Object[] args) throws Throwable
|
abstract protected Object _writeReplace(Object proxy) throws ObjectStreamException
|
protected void checkAuthorization(Method method) throws OpenEJBException {
}
|
protected Throwable convertException(Throwable e,
Method method,
Class interfce) {
boolean rmiRemote = java.rmi.Remote.class.isAssignableFrom(interfce);
if (e instanceof TransactionRequiredException) {
if (!rmiRemote && interfaceType.isBusiness()) {
return new EJBTransactionRequiredException(e.getMessage()).initCause(getCause(e));
} else if (interfaceType.isLocal()) {
return new TransactionRequiredLocalException(e.getMessage()).initCause(getCause(e));
} else {
return e;
}
}
if (e instanceof TransactionRolledbackException) {
if (!rmiRemote && interfaceType.isBusiness()) {
return new EJBTransactionRolledbackException(e.getMessage()).initCause(getCause(e));
} else if (interfaceType.isLocal()) {
return new TransactionRolledbackLocalException(e.getMessage()).initCause(getCause(e));
} else {
return e;
}
}
if (e instanceof NoSuchObjectException) {
if (!rmiRemote && interfaceType.isBusiness()) {
return new NoSuchEJBException(e.getMessage()).initCause(getCause(e));
} else if (interfaceType.isLocal()) {
return new NoSuchObjectLocalException(e.getMessage()).initCause(getCause(e));
} else {
return e;
}
}
if (e instanceof RemoteException) {
if (!rmiRemote && interfaceType.isBusiness()) {
return new EJBException(e.getMessage()).initCause(getCause(e));
} else if (interfaceType.isLocal()) {
return new EJBException(e.getMessage()).initCause(getCause(e));
} else {
return e;
}
}
if (e instanceof AccessException) {
if (!rmiRemote && interfaceType.isBusiness()) {
return new AccessLocalException(e.getMessage()).initCause(getCause(e));
} else if (interfaceType.isLocal()) {
return new AccessLocalException(e.getMessage()).initCause(getCause(e));
} else {
return e;
}
}
for (Class< ? > type : method.getExceptionTypes()) {
if (type.isAssignableFrom(e.getClass())) {
return e;
}
}
// Exception is undeclared
// Try and find a runtime exception in there
while (e.getCause() != null && !(e instanceof RuntimeException)) {
e = e.getCause();
}
return e;
}
Renamed method so it shows up with a much more understandable purpose as it
will be the top element in the stacktrace |
protected Object[] copyArgs(Object[] objects) throws ClassNotFoundException, IOException {
/*
while copying the arguments is necessary. Its not necessary to copy the array itself,
because they array is created by the Proxy implementation for the sole purpose of
packaging the arguments for the InvocationHandler.invoke( ) method. Its ephemeral
and their for doesn't need to be copied.
*/
for (int i = 0; i < objects.length; i++) {
objects[i] = copyObj(objects[i]);
}
return objects;
}
|
protected Object copyObj(Object object) throws ClassNotFoundException, IOException {
// Check for primitive and other known class types that are immutable. If detected
// we can safely return them.
if (object == null) return null;
Class ooc = object.getClass();
if ((ooc == int.class ) ||
(ooc == String.class ) ||
(ooc == long.class ) ||
(ooc == boolean.class ) ||
(ooc == byte.class ) ||
(ooc == float.class ) ||
(ooc == double.class ) ||
(ooc == short.class ) ||
(ooc == Long.class ) ||
(ooc == Boolean.class ) ||
(ooc == Byte.class ) ||
(ooc == Character.class ) ||
(ooc == Float.class ) ||
(ooc == Double.class ) ||
(ooc == Short.class ) ||
(ooc == BigDecimal.class ))
{
return object;
}
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream(128);
ObjectOutputStream out = new ObjectOutputStream(baos);
out.writeObject(object);
out.close();
} catch (NotSerializableException e) {
throw (IOException) new NotSerializableException(e.getMessage()+" : The EJB specification restricts remote interfaces to only serializable data types. This can be disabled for in-vm use with the "+OPENEJB_LOCALCOPY+"=false system property.").initCause(e);
}
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream in = new EjbObjectInputStream(bais);
Object obj = in.readObject();
return obj;
}
|
public boolean equals(Object obj) {
try {
obj = ProxyManager.getInvocationHandler(obj);
} catch (IllegalArgumentException e) {
return false;
}
BaseEjbProxyHandler other = (BaseEjbProxyHandler) obj;
if (primaryKey == null) {
return other.primaryKey == null && deploymentID.equals(other.deploymentID);
} else {
return primaryKey.equals(other.primaryKey) && deploymentID.equals(other.deploymentID);
}
}
|
protected Throwable getCause(Throwable e) {
if (e != null && e.getCause() != null) {
return e.getCause();
}
return e;
}
|
public CoreDeploymentInfo getDeploymentInfo() {
CoreDeploymentInfo info = deploymentInfo.get();
if (info == null|| info.isDestroyed()){
invalidateReference();
throw new IllegalStateException("Bean '"+deploymentID+"' has been undeployed.");
}
return info;
}
|
public List getInterfaces() {
Set< Class > classes = interfaces.keySet();
return new ArrayList(classes);
}
|
protected Class getInvokedInterface(Method method) {
// Home's only have one interface ever. We don't
// need to verify that the method invoked is in
// it's interface.
Class mainInterface = getMainInterface();
if (interfaceType.isHome()) return mainInterface;
Class declaringClass = method.getDeclaringClass();
// If our "main" interface is or extends the method's declaring class
// then we're good. We know the main interface has the method being
// invoked and it's safe to return it as the invoked interface.
if (declaringClass.isAssignableFrom(mainInterface)){
return mainInterface;
}
// If the method being invoked isn't in the "main" interface
// we need to find a suitable interface or throw an exception.
for (Class secondaryInterface : interfaces.keySet()) {
if (declaringClass.isAssignableFrom(secondaryInterface)){
return secondaryInterface;
}
}
// We couldn't find an implementing interface. Where did this
// method come from??? Freak occurence. Throw an exception.
throw new IllegalStateException("Received method invocation and cannot determine corresponding business interface: method=" + method);
}
This method should be called to determine the corresponding
business interface class to name as the invoking interface.
This method should NOT be called on non-business-interface
methods the proxy has such as java.lang.Object or IntraVmProxy. |
public Hashtable getLiveHandleRegistry() {
CoreDeploymentInfo deploymentInfo = getDeploymentInfo();
ProxyRegistry proxyRegistry = deploymentInfo.get(ProxyRegistry.class);
if (proxyRegistry == null){
proxyRegistry = new ProxyRegistry();
deploymentInfo.set(ProxyRegistry.class, proxyRegistry);
}
return proxyRegistry.liveHandleRegistry;
}
|
public Class getMainInterface() {
return mainInterface.get();
}
|
abstract public ProxyInfo getProxyInfo()
|
public int hashCode() {
if (primaryKey == null) {
return deploymentID.hashCode();
} else {
return primaryKey.hashCode();
}
}
|
protected void invalidateAllHandlers(Object key) {
HashSet< BaseEjbProxyHandler > set = (HashSet) getLiveHandleRegistry().remove(key);
if (set == null) return;
synchronized (set) {
for (BaseEjbProxyHandler handler : set) {
handler.invalidateReference();
}
}
}
|
public void invalidateReference() {
this.container = null;
this.setDeploymentInfo(null);
this.isInvalidReference = true;
}
|
public Object invoke(Object proxy,
Method method,
Object[] args) throws Throwable {
if (isInvalidReference) {
if (interfaceType.isComponent() && interfaceType.isLocal()){
throw new NoSuchObjectLocalException("reference is invalid");
} else if (interfaceType.isComponent() || java.rmi.Remote.class.isAssignableFrom(method.getDeclaringClass())) {
throw new NoSuchObjectException("reference is invalid");
} else {
throw new javax.ejb.NoSuchEJBException("reference is invalid");
}
}
getDeploymentInfo(); // will throw an exception if app has been undeployed.
if (method.getDeclaringClass() == Object.class) {
final String methodName = method.getName();
if (methodName.equals("toString")) return toString();
else if (methodName.equals("equals")) return equals(args[0]) ? Boolean.TRUE : Boolean.FALSE;
else if (methodName.equals("hashCode")) return new Integer(hashCode());
else
throw new UnsupportedOperationException("Unkown method: " + method);
} else if (method.getDeclaringClass() == IntraVmProxy.class) {
final String methodName = method.getName();
if (methodName.equals("writeReplace")) return _writeReplace(proxy);
else
throw new UnsupportedOperationException("Unkown method: " + method);
}
Class interfce = getInvokedInterface(method);
// Should we copy arguments as required by the specification?
if (doIntraVmCopy && !doCrossClassLoaderCopy) {
if (args != null && args.length > 0) {
IntraVmCopyMonitor.preCopyOperation();
try {
args = copyArgs(args);
} finally {
IntraVmCopyMonitor.postCopyOperation();
}
}
Object returnObj = null;
try {
returnObj = _invoke(proxy, interfce, method, args);
} catch (Throwable throwable) {
// exceptions are return values and must be coppied
IntraVmCopyMonitor.preCopyOperation();
try {
throwable = (Throwable) copyObj(throwable);
throw convertException(throwable, method, interfce);
} finally {
IntraVmCopyMonitor.postCopyOperation();
}
}
if (returnObj != null) {
IntraVmCopyMonitor.preCopyOperation();
try {
returnObj = copyObj(returnObj);
} finally {
IntraVmCopyMonitor.postCopyOperation();
}
}
return returnObj;
} else if (doIntraVmCopy) {
// copy method and arguments to EJB's class loader
IntraVmCopyMonitor.preCrossClassLoaderOperation();
ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getDeploymentInfo().getClassLoader());
try {
if (args != null && args.length > 0) {
args = copyArgs(args);
}
method = copyMethod(method);
interfce = (Class) copyObj(interfce);
} finally {
Thread.currentThread().setContextClassLoader(oldClassLoader);
IntraVmCopyMonitor.postCrossClassLoaderOperation();
}
// invoke method
Object returnObj = null;
try {
returnObj = _invoke(proxy, interfce, method, args);
} catch (Throwable throwable) {
// exceptions are return values and must be coppied
IntraVmCopyMonitor.preCrossClassLoaderOperation();
try {
throwable = (Throwable) copyObj(throwable);
throw convertException(throwable, method, interfce);
} finally {
IntraVmCopyMonitor.postCrossClassLoaderOperation();
}
}
if (returnObj != null) {
IntraVmCopyMonitor.preCrossClassLoaderOperation();
try {
returnObj = copyObj(returnObj);
} finally {
IntraVmCopyMonitor.postCrossClassLoaderOperation();
}
}
return returnObj;
} else {
try {
/*
* The EJB 1.1 specification requires that arguments and return values between beans adhere to the
* Java RMI copy semantics which requires that the all arguments be passed by value (copied) and
* never passed as references. However, it is possible for the system administrator to turn off the
* copy operation so that arguments and return values are passed by reference as a performance optimization.
* Simply setting the org.apache.openejb.core.EnvProps.INTRA_VM_COPY property to FALSE will cause
* IntraVM to bypass the copy operations; arguments and return values will be passed by reference not value.
* This property is, by default, always TRUE but it can be changed to FALSE by setting it as a System property
* or a property of the Property argument when invoking OpenEJB.init(props). The doIntraVmCopy variable is set to that
* property in the static block for this class.
*/
return _invoke(proxy, interfce, method, args);
} catch (Throwable t) {
throw convertException(t, method, interfce);
}
}
}
|
protected void registerHandler(Object key,
BaseEjbProxyHandler handler) {
HashSet set = (HashSet) getLiveHandleRegistry().get(key);
if (set != null) {
synchronized (set) {
set.add(handler);
}
} else {
set = new HashSet();
set.add(handler);
getLiveHandleRegistry().put(key, set);
}
}
|
public void setDeploymentInfo(CoreDeploymentInfo deploymentInfo) {
this.deploymentInfo = new WeakReference< CoreDeploymentInfo >(deploymentInfo);
}
|
public void setIntraVmCopyMode(boolean on) {
doIntraVmCopy = on;
}
|
public String toString() {
String name = null;
try {
name = getProxyInfo().getInterface().getName();
} catch (Exception e) {
}
return "proxy=" + name + ";deployment=" + this.deploymentID + ";pk=" + this.primaryKey;
}
|