/** * An identifier for an EJB proxy invocation target instance, suitable for use as a hash key or a * serialized token. * * @param <T> the interface type */ public abstract class EJBLocator<T> implements Serializable { private static final long serialVersionUID = -7306257085240447972L; private final Class<T> viewType; private final String appName; private final String moduleName; private final String beanName; private final String distinctName; private final Affinity affinity; private final transient Class<? extends T> proxyClass; private final transient Constructor<? extends T> proxyConstructor; private final transient int hashCode; private static final FieldSetter hashCodeSetter = FieldSetter.get(EJBLocator.class, "hashCode"); private static final FieldSetter proxyClassSetter = FieldSetter.get(EJBLocator.class, "proxyClass"); private static final FieldSetter proxyConstructorSetter = FieldSetter.get(EJBLocator.class, "proxyConstructor"); EJBLocator( final Class<T> viewType, final String appName, final String moduleName, final String beanName, final String distinctName, final Affinity affinity) { if (viewType == null) { throw Logs.MAIN.paramCannotBeNull("viewType"); } if (appName == null) { throw Logs.MAIN.paramCannotBeNull("appName"); } if (moduleName == null) { throw Logs.MAIN.paramCannotBeNull("moduleName"); } if (beanName == null) { throw Logs.MAIN.paramCannotBeNull("beanName"); } if (distinctName == null) { throw Logs.MAIN.paramCannotBeNull("distinctName"); } this.viewType = viewType; this.appName = appName; this.moduleName = moduleName; this.beanName = beanName; this.distinctName = distinctName; this.affinity = affinity == null ? Affinity.NONE : affinity; if (System.getSecurityManager() == null) { proxyClass = Proxy.getProxyClass(viewType.getClassLoader(), viewType).asSubclass(viewType); try { proxyConstructor = proxyClass.getConstructor(InvocationHandler.class); } catch (NoSuchMethodException e) { throw new NoSuchMethodError("No valid constructor found on proxy class"); } } else { proxyClass = AccessController.doPrivileged( new PrivilegedAction<Class<? extends T>>() { @Override public Class<? extends T> run() { return Proxy.getProxyClass(viewType.getClassLoader(), viewType) .asSubclass(viewType); } }); proxyConstructor = AccessController.doPrivileged( new PrivilegedAction<Constructor<? extends T>>() { @Override public Constructor<? extends T> run() { try { return proxyClass.getConstructor(InvocationHandler.class); } catch (NoSuchMethodException e) { throw new NoSuchMethodError("No valid constructor found on proxy class"); } } }); } hashCode = calcHashCode(viewType, appName, moduleName, beanName, distinctName); } private static int calcHashCode( final Class<?> viewType, final String appName, final String moduleName, final String beanName, final String distinctName) { return viewType.hashCode() * 13 + (appName.hashCode() * 13 + (moduleName.hashCode() * 13 + (beanName.hashCode() * 13 + (distinctName.hashCode())))); } /** * Get the view type of this locator. * * @return the view type */ public Class<T> getViewType() { return viewType; } /** * Get the application name. * * @return the application name */ public String getAppName() { return appName; } /** * Get the module name. * * @return the module name */ public String getModuleName() { return moduleName; } /** * Get the EJB bean name. * * @return the EJB bean name */ public String getBeanName() { return beanName; } /** * Get the module distinct name. * * @return the module distinct name */ public String getDistinctName() { return distinctName; } /** * Get the locator affinity. * * @return the locator affinity */ public Affinity getAffinity() { return affinity; } /** * Get the hash code for this instance. * * @return the hash code for this instance */ public int hashCode() { return hashCode; } /** * Determine whether this object is equal to another. * * @param other the other object * @return {@code true} if they are equal, {@code false} otherwise */ public boolean equals(Object other) { return other instanceof EJBLocator && equals((EJBLocator<?>) other); } /** * Get the proxy class for this locator. * * @return the proxy class */ public Class<? extends T> getProxyClass() { return proxyClass; } /** * Get the proxy class constructor for this locator. A proxy class constructor accepts a single * argument of type {@link InvocationHandler}. * * @return the proxy constructor */ public Constructor<? extends T> getProxyConstructor() { return proxyConstructor; } /** * Create a proxy instance using the cached proxy class. * * @param invocationHandler the invocation handler to use * @return the proxy instance */ public T createProxyInstance(InvocationHandler invocationHandler) { if (invocationHandler == null) { throw Logs.MAIN.paramCannotBeNull("Invocation handler"); } try { return proxyConstructor.newInstance(invocationHandler); } catch (InstantiationException e) { throw new InstantiationError(e.getMessage()); } catch (IllegalAccessException e) { throw new IllegalAccessError(e.getMessage()); } catch (InvocationTargetException e) { throw new UndeclaredThrowableException(e.getCause()); } } /** * Determine whether this object is equal to another. * * @param other the other object * @return {@code true} if they are equal, {@code false} otherwise */ public boolean equals(EJBLocator<?> other) { return this == other || other != null && hashCode == other.hashCode && appName.equals(other.appName) && moduleName.equals(other.moduleName) && beanName.equals(other.beanName) && distinctName.equals(other.distinctName); } private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { ois.defaultReadObject(); final Class<? extends T> proxyType = Proxy.getProxyClass(viewType.getClassLoader(), viewType).asSubclass(viewType); final Constructor<? extends T> proxyConstructor; try { proxyConstructor = proxyType.getConstructor(InvocationHandler.class); } catch (NoSuchMethodException e) { throw new NoSuchMethodError("No valid constructor found on proxy class"); } proxyClassSetter.set(this, proxyType); proxyConstructorSetter.set(this, proxyConstructor); hashCodeSetter.setInt( this, calcHashCode(viewType, appName, moduleName, beanName, distinctName)); } }
/** * A locator for an entity EJB. * * @param <T> the remote view type */ public final class EntityEJBLocator<T extends EJBObject> extends EJBLocator<T> { private static final long serialVersionUID = 6674116259124568398L; private final Object primaryKey; private final transient int hashCode; private static final FieldSetter hashCodeSetter = FieldSetter.get(EntityEJBLocator.class, "hashCode"); /** * Construct a new instance. * * @param viewType the view type * @param appName the application name * @param moduleName the module name * @param beanName the bean name * @param distinctName the distinct name * @param primaryKey the entity primary key */ public EntityEJBLocator( final Class<T> viewType, final String appName, final String moduleName, final String beanName, final String distinctName, final Object primaryKey) { super(viewType, appName, moduleName, beanName, distinctName, Affinity.NONE); if (primaryKey == null) { throw Logs.MAIN.paramCannotBeNull("primary key"); } this.primaryKey = primaryKey; hashCode = primaryKey.hashCode() * 13 + super.hashCode(); } /** * Get the primary key for the referenced entity. * * @return the primary key for the referenced entity */ public Object getPrimaryKey() { return primaryKey; } /** * Determine whether this object is equal to another. * * @param other the other object * @return {@code true} if they are equal, {@code false} otherwise */ public boolean equals(final Object other) { return other instanceof EntityEJBLocator && equals((EntityEJBLocator<?>) other); } /** * Determine whether this object is equal to another. * * @param other the other object * @return {@code true} if they are equal, {@code false} otherwise */ public boolean equals(final EJBLocator<?> other) { return other instanceof EntityEJBLocator && equals((EntityEJBLocator<?>) other); } /** * Determine whether this object is equal to another. * * @param other the other object * @return {@code true} if they are equal, {@code false} otherwise */ public boolean equals(final EntityEJBLocator<?> other) { return super.equals(other) && primaryKey.equals(other.primaryKey); } /** * Get the hash code for this instance. * * @return the hash code for this instance */ public int hashCode() { return hashCode; } private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { ois.defaultReadObject(); hashCodeSetter.setInt(this, primaryKey.hashCode() * 13 + super.hashCode()); } @Override public String toString() { return "EntityEJBLocator{" + "appName='" + getAppName() + '\'' + ", moduleName='" + getModuleName() + '\'' + ", distinctName='" + getDistinctName() + '\'' + ", beanName='" + getBeanName() + '\'' + ", view='" + getViewType() + '\'' + ", primaryKey='" + getPrimaryKey() + '\'' + '}'; } }
/** * A locator for an entity EJB. * * @param <T> the remote view type */ public final class EntityEJBLocator<T extends EJBObject> extends EJBLocator<T> { private static final long serialVersionUID = 6674116259124568398L; private final Object primaryKey; private final transient int hashCode; private static final FieldSetter hashCodeSetter = FieldSetter.get(EntityEJBLocator.class, "hashCode"); /** * Construct a new instance. * * @param viewType the view type * @param appName the application name * @param moduleName the module name * @param beanName the bean name * @param primaryKey the entity primary key */ public EntityEJBLocator( final Class<T> viewType, final String appName, final String moduleName, final String beanName, final Object primaryKey) { this(viewType, appName, moduleName, beanName, null, primaryKey, Affinity.NONE); } /** * Construct a new instance. * * @param viewType the view type * @param appName the application name * @param moduleName the module name * @param beanName the bean name * @param primaryKey the entity primary key * @param affinity the affinity */ public EntityEJBLocator( final Class<T> viewType, final String appName, final String moduleName, final String beanName, final Object primaryKey, final Affinity affinity) { this(viewType, appName, moduleName, beanName, null, primaryKey, affinity); } /** * Construct a new instance. * * @param viewType the view type * @param appName the application name * @param moduleName the module name * @param beanName the bean name * @param distinctName the distinct name * @param primaryKey the entity primary key */ public EntityEJBLocator( final Class<T> viewType, final String appName, final String moduleName, final String beanName, final String distinctName, final Object primaryKey) { this(viewType, appName, moduleName, beanName, distinctName, primaryKey, Affinity.NONE); } /** * Construct a new instance. * * @param viewType the view type * @param appName the application name * @param moduleName the module name * @param beanName the bean name * @param distinctName the distinct name * @param primaryKey the entity primary key * @param affinity the affinity */ public EntityEJBLocator( final Class<T> viewType, final String appName, final String moduleName, final String beanName, final String distinctName, final Object primaryKey, final Affinity affinity) { super(viewType, appName, moduleName, beanName, distinctName, affinity); if (primaryKey == null) { throw Logs.MAIN.paramCannotBeNull("primary key"); } this.primaryKey = primaryKey; hashCode = primaryKey.hashCode() * 13 + super.hashCode(); } /** * Construct a new instance. This constructor creates a copy of the original locator, but with a * new affinity. * * @param original the original locator * @param newAffinity the new affinity */ public EntityEJBLocator(final EntityEJBLocator<T> original, final Affinity newAffinity) { super(original, newAffinity); this.primaryKey = original.primaryKey; hashCode = primaryKey.hashCode() * 13 + super.hashCode(); } public EJBLocator<T> withNewAffinity(final Affinity affinity) { return new EntityEJBLocator<T>(this, affinity); } @SuppressWarnings("unchecked") public <S> EntityEJBLocator<? extends S> narrowTo(final Class<S> type) { return (EntityEJBLocator<? extends S>) super.narrowTo(type); } @SuppressWarnings("unchecked") public <S extends EJBObject> EntityEJBLocator<? extends S> narrowAsEntity(final Class<S> type) { if (type.isAssignableFrom(getViewType())) { return (EntityEJBLocator<? extends S>) this; } throw new ClassCastException(type.toString()); } /** * Get the primary key for the referenced entity. * * @return the primary key for the referenced entity */ public Object getPrimaryKey() { return primaryKey; } /** * Determine whether this object is equal to another. * * @param other the other object * @return {@code true} if they are equal, {@code false} otherwise */ public boolean equals(final Object other) { return other instanceof EntityEJBLocator && equals((EntityEJBLocator<?>) other); } /** * Determine whether this object is equal to another. * * @param other the other object * @return {@code true} if they are equal, {@code false} otherwise */ public boolean equals(final EJBLocator<?> other) { return other instanceof EntityEJBLocator && equals((EntityEJBLocator<?>) other); } /** * Determine whether this object is equal to another. * * @param other the other object * @return {@code true} if they are equal, {@code false} otherwise */ public boolean equals(final EntityEJBLocator<?> other) { return super.equals(other) && primaryKey.equals(other.primaryKey); } /** * Get the hash code for this instance. * * @return the hash code for this instance */ public int hashCode() { return hashCode; } private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { ois.defaultReadObject(); hashCodeSetter.setInt(this, primaryKey.hashCode() * 13 + super.hashCode()); } @Override public String toString() { return String.format("%s, primary key is %s", super.toString(), getPrimaryKey()); } }