/** JNDI object factory so the proxy can be used as a resource. */
  public Object getObjectInstance(
      Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
    Reference ref = (Reference) obj;

    String api = null;
    String url = null;
    String user = null;
    String password = null;

    for (int i = 0; i < ref.size(); i++) {
      RefAddr addr = ref.get(i);

      String type = addr.getType();
      String value = (String) addr.getContent();

      if (type.equals("type")) api = value;
      else if (type.equals("url")) url = value;
      else if (type.equals("user")) setUser(value);
      else if (type.equals("password")) setPassword(value);
    }

    if (url == null) throw new NamingException("`url' must be configured for HessianProxyFactory.");
    // XXX: could use meta protocol to grab this
    if (api == null)
      throw new NamingException("`type' must be configured for HessianProxyFactory.");

    ClassLoader loader = Thread.currentThread().getContextClassLoader();
    Class apiClass = Class.forName(api, false, loader);

    return create(apiClass, url);
  }
  /**
   * Creates a new proxy with the specified URL. The returned object is a proxy with the interface
   * specified by api.
   *
   * <pre>
   * String url = "http://localhost:8080/ejb/hello");
   * HelloHome hello = (HelloHome) factory.create(HelloHome.class, url);
   * </pre>
   *
   * @param api the interface the proxy class needs to implement
   * @param url the URL where the client object is located.
   * @return a proxy to the object with the specified interface.
   */
  public Object create(Class api, String urlName, ClassLoader loader) throws MalformedURLException {
    URL url = new URL(urlName);

    HessianProxy handler = new HessianProxy(this, url);

    return Proxy.newProxyInstance(
        api.getClassLoader(), new Class[] {api, HessianRemoteObject.class}, handler);
  }
  /**
   * Creates a new proxy with the specified URL. The API class uses the java.api.class value from
   * _hessian_
   *
   * @param urlName the URL where the client object is located.
   * @return a proxy to the object with the specified interface.
   * @throws java.net.MalformedURLException if URL object cannot be created with the provided
   *     urlName
   * @throws ClassNotFoundException if the current Thread's contextClassLoader cannot find the api
   *     class
   */
  @SuppressWarnings({"unchecked"})
  public Object create(String urlName) throws MalformedURLException, ClassNotFoundException {
    HessianMetaInfoAPI metaInfo = create(HessianMetaInfoAPI.class, urlName);
    String apiClassName = (String) metaInfo._hessian_getAttribute("java.api.class");

    if (apiClassName == null) {
      throw new HessianRuntimeException(urlName + " has an unknown api.");
    }
    ClassLoader loader = Thread.currentThread().getContextClassLoader();
    Class<Object> apiClass = (Class<Object>) Class.forName(apiClassName, false, loader);
    return create(apiClass, urlName);
  }
  /**
   * Creates a new proxy with the specified URL. The API class uses the java.api.class value from
   * _hessian_
   *
   * @param url the URL where the client object is located.
   * @return a proxy to the object with the specified interface.
   */
  public Object create(String url) throws MalformedURLException, ClassNotFoundException {
    HessianMetaInfoAPI metaInfo;

    metaInfo = (HessianMetaInfoAPI) create(HessianMetaInfoAPI.class, url);

    String apiClassName = (String) metaInfo._hessian_getAttribute("java.api.class");

    if (apiClassName == null) throw new HessianRuntimeException(url + " has an unknown api.");

    ClassLoader loader = Thread.currentThread().getContextClassLoader();

    Class apiClass = Class.forName(apiClassName, false, loader);

    return create(apiClass, url);
  }