Example #1
0
/**
 * 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());
  }
}