package examples.xml.jms;

import com.sun.java.util.collections.Map;
import com.sun.java.util.collections.HashMap;
import com.sun.java.util.collections.Set;
import java.io.InputStream;
import java.io.IOException;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import weblogic.utils.Debug;

/**
 * This is a entity resolver which can be used with parsers to 
 * resolve XML external entities to local class resources.  Use 
 * <tt>addEntityResource</tt> to add a mapping between a publicId and 
 * an external XML entity. The XML entity must be stored in the same 
 * directory as the associated <tt>resourceClass</tt> specified in the 
 * <tt>addEntityResource</tt> call.
 *
 * @author Copyright (c) 2000 by BEA Systems, Inc. All Rights Reserved.
 */

public class ResourceEntityResolver implements EntityResolver 
{

  private final static boolean debug = false;
  private final static boolean verbose = false;

  /**
   * This contains mappings between XML public IDs and the local
   * resources that they will map to.
   */
  protected Map entityCatalog = new HashMap();

  /**
   * Resolve an entity passed to us by the XML parser. If the publicId 
   * of the entity is registered, we return null which signals the 
   * parser to use its default entity resolver.
   */
  public InputSource resolveEntity(String publicId, String systemId) 
    throws SAXException, IOException 
  {

    InputSource ins = null;

    if(verbose) {
      System.out.println("ResourceEntityResolver: asked to resolve public "
                         + publicId + " in systemId " + systemId);
    }

    EntityResource resource = 
      (EntityResource) entityCatalog.get(publicId);

    if (debug) {
      Debug.assert(resource != null);
    }

    InputStream resin = resource.getResourceAsStream();

    if (resin == null) {
      if (verbose) {
        System.out.println(
          "ResourceEntityResolver: did not resolve entity for publicId = " +
          publicId + " with resource name " + resource.getResourceName()
        );
      }
      // we didn't find the local resource, so we return null to signal the
      // parser that it must resolve the entity itself.
      return null;
    }
    
    ins = new InputSource(resin);
    ins.setPublicId(publicId);
    return ins;
  }


  /**
   * Specify a mapping between the publicId of an external XML entity
   * and a local resource.
   */
  public void addEntityResource(String publicId, String resourceName, 
    Class resourceClass) 
  {
    
    if (debug) {
      Debug.assert(publicId != null, "publicId must not be null");
    }

    if (verbose) {
      System.out.println("Adding entity resource " + resourceName + 
        "@" + resourceClass + " for publicId = " + publicId);
    }
    
    entityCatalog.put(publicId, 
      new EntityResource(resourceName, resourceClass));
  }
  
  /**
   * Contains information about a resource mapped to an entity, 
   * specifically the resource name and the class with which the 
   * resource is associated.
   */
  protected static class EntityResource {
    private final String name;
    private final Class clazz;
    public EntityResource(String name, Class clazz) 
    {
      if (ResourceEntityResolver.debug) {
        Debug.assert(name != null, "Resource name must not be null");
        Debug.assert(clazz != null, "Resource class must not be null");
      }
      this.name = name;
      this.clazz = clazz;
    }
    public String getResourceName() { return name; }
    public Class getResourceClass() { return clazz; }
    public InputStream getResourceAsStream() {
      return clazz.getResourceAsStream(name);
    }
  }
}

