Package cookxml.core

Source Code of cookxml.core.CookXml

/*
* (c) Copyright 2004 by Heng Yuan
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* ITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package cookxml.core;

import java.io.File;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;
import javax.xml.parsers.DocumentBuilder;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;

import cookxml.core.exception.CookXmlException;
import cookxml.core.exception.InvalidInputException;
import cookxml.core.exceptionhandler.DebugExceptionHandler;
import cookxml.core.interfaces.ExceptionHandler;
import cookxml.core.interfaces.StringHook;
import cookxml.core.interfaces.TagLibrary;
import cookxml.core.interfaces.VarLookup;
import cookxml.core.stringhook.ResourceBundleStringHook;
import cookxml.core.util.DocumentElement;

/**
* This class is a general purpose XML configurator.
*
* @author Heng Yuan
* @version $Id: CookXml.java 244 2007-06-07 04:29:13Z coconut $
* @since CookXml 1.0
*/
public class CookXml
{
  private static ExceptionHandler s_defaultExceptionHandler = DebugExceptionHandler.getInstance ();

  private static boolean s_defaultAccessible = false;

  private static ClassLoader s_defaultClassLoader = CookXml.class.getClassLoader ();

  /**
   * Obtain the default ExceptionHandler for all instances of CookXml.
   * @return  the default ExceptionHandler for all instances of CookXml
   * @see ExceptionHandler
   * @since CookXml 2.0
   */
  public static ExceptionHandler getDefaultExceptionHandler ()
  {
    return s_defaultExceptionHandler;
  }

  /**
   * Sets the default ExceptionHandler for all instances of CookXml.
   * @param   defaultExceptionHandler
   *          the default ExceptionHandler to be used
   * @see ExceptionHandler
   * @since CookXml 2.0
   */
  public static void setDefaultExceptionHandler (ExceptionHandler defaultExceptionHandler)
  {
    s_defaultExceptionHandler = defaultExceptionHandler;
  }

  /**
   * Setting this flag to true to allow CookXml to read/write non-public variables
   * (including package scope, protected, and private variables) by default.
   * <p>
   * Note, reading/writing non-public variable should be avoided for Web Start
   * applications or applications that run in a sandbox, as such action can
   * generate a SecurityException.
   * <p>
   * Usually, it is rather rare to have frequent access to a single variable.
   * So, performance-wise should be okay.  If you read/write a particular
   * variable more often, consider to cache the object.
   *
   * @see cookxml.core.exception.AccessException
   * @param   accessible  if CookXml should attempt to access non-public variables
   * @since CookXml 2.3
   */
  public static void setDefaultAccessible (boolean accessible)
  {
    s_defaultAccessible = accessible;
  }

  /**
   * Returns if CookXml by default should attempt to access non-public variables.
   * @return  if CookXml by default should attempt to access non-public variables
   * @since CookXml 2.3
   */
  public static boolean isDefaultAccessible ()
  {
    return s_defaultAccessible;
  }

  /**
   * Obtain the default ClassLoader that is used to locate resources.
   * @return  the default ClassLoader
   * @since CookXml 2.3
   */
  public static ClassLoader getDefaultClassLoader ()
  {
    return s_defaultClassLoader;
  }

  /**
   * Set the default ClassLaoder that is used to locate resouces.
   * @param   defaultClassLoader  the default ClassLoader to be used.
   * @since CookXml 2.3
   */
  public static void setDefaultClassLoader (ClassLoader defaultClassLoader)
  {
    s_defaultClassLoader = defaultClassLoader;
  }

  /**
   * This function is supposed to work in conjunction with assert to generate
   * a debug message but does not really throw an Exception
   *
   * @param  msg the message to be printed.
   * @return  true
   */
  public static boolean debug (String msg)
  {
    if (msg != null)
      System.out.println (msg);
    return true;
  }

  /**
   * This function is supposed to work in conjunction with assert to generate
   * a debug message but does not really throw an Exception
   *
   * @param  msg the message to be printed.
   * @param  ex the exception message to be printed.
   * @return  true
   */
  public static boolean debug (String msg, Exception ex)
  {
    if (msg != null)
      System.out.println (msg);
    if (ex != null)
      ex.printStackTrace (System.out);
    return true;
  }

  /**
   * This function is supposed to work in conjunction with assert to generate
   * a debug message but does not really throw an Exception
   *
   * @param  ex the exception message to be printed.
   * @return  true
   */
  public static boolean debug (Exception ex)
  {
    if (ex != null)
      ex.printStackTrace (System.out);
    return true;
  }

  private final TagLibrary m_tagLibrary;
  private Object m_rootObj;
  private DocumentBuilder m_docBuilder;
  private VarLookup m_varLookup;
  private ResourceBundle m_bundle;
  private StringHook m_userhook;
  private ExceptionHandler m_exceptionHandler;

  private boolean m_accessible = s_defaultAccessible;
  private final Map m_idMap = new HashMap ();
  private ClassLoader m_classLoader = s_defaultClassLoader;

  /**
   * constructor.
   *
   * @param  builder the document builder use to parse the xml document.
   * @param  tagLibrary the tag library to be used.
   * @param  varObj inside where all the variables are contained.
   */
  public CookXml (DocumentBuilder builder, TagLibrary tagLibrary, Object varObj)
  {
    m_docBuilder = builder;
    m_tagLibrary = tagLibrary;
    if (varObj != null)
      m_varLookup = new DefaultVarLookup (varObj);
  }

  /**
   * constructor.
   *
   * @param  builder the document builder use to parse the xml document.
   * @param  tagLibrary the tag library to be used.
   * @param  varLookup a handler for looking up variables
   */
  public CookXml (DocumentBuilder builder, TagLibrary tagLibrary, VarLookup varLookup)
  {
    m_docBuilder = builder;
    m_tagLibrary = tagLibrary;
    m_varLookup = varLookup;
  }

  /**
   * returns the tag library used by this CookXml object
   *
   * @return the tag library used by this CookXml object
   */
  public TagLibrary getTagLibrary ()
  {
    return m_tagLibrary;
  }

  /**
   * get the element associated with the id.
   *
   * @param  id the id to be retrieved.
   * @return  the information associated with the id.
   */
  public IdReference getId (String id)
  {
    return (IdReference)m_idMap.get (id);
  }

  /**
   * Save an element with an id in a map such that this element can be referenced later.
   *
   * @param  id the id to be saved.
   * @param  tag the tag name.
   * @param  obj the object associated with the tag.
   */
  public void setId (String id, String ns, String tag, Object obj)
  {
    m_idMap.put (id, new IdReference (id, ns, tag, obj));
  }

  /**
   * Call this function to start decoding the input.  The input can be
   * a string (which would be looked up using ClassLoader), a File, an InputStream,
   * or an InputSource.
   *
   * @param  input the input source
   * @return  the object constructed.
   */
  public Object xmlDecode (Object input) throws CookXmlException
  {
    return xmlDecode (input, null, null, null);
  }

  /**
   * Call this function to start decoding the input.  The input can be
   * a string (which would be looked up using ClassLoader), a File, an InputStream,
   * or an InputSource.
   *
   * @param parentTag the assumed parent tag
   * @param parentObj the assumed parentObj
   * @param  input the input source
   * @return  the object constructed.
   */
  public Object xmlDecode (Object input, String parentNS, String parentTag, Object parentObj) throws CookXmlException
  {
    try
    {
      DocumentBuilder builder = m_docBuilder;
      Document doc = null;
      Element elm = null;
      if (input instanceof String)
      {
        InputStream inputStream = m_classLoader.getResourceAsStream ((String)input);
        if (inputStream == null)
          doc = builder.parse ((String)input);
        else
          doc = builder.parse (inputStream);
      }
      else if (input instanceof InputStream)
        doc = builder.parse ((InputStream)input);
      else if (input instanceof File)
        doc = builder.parse ((File)input);
      else if (input instanceof InputSource)
        doc = builder.parse ((InputSource)input);
      else if (input instanceof Document)
        doc = (Document)input;
      else if (input instanceof DocumentElement)
      {
        doc = ((DocumentElement)input).doc;
        elm = ((DocumentElement)input).element;
      }
      if (doc == null)
      {
        getExceptionHandler ().handleException (null, new InvalidInputException (input));
        return null;
      }
      StringHook stringHook = null;
      if(m_userhook != null)
        stringHook = m_userhook;
      else if (m_bundle != null)
        stringHook = new ResourceBundleStringHook (m_bundle);
      DecodeEngine decodeEngine = DecodeEngine.createDecodeEngine (this, m_varLookup, stringHook);
      decodeEngine.setDocument (doc);
      if (elm == null)
        elm = doc.getDocumentElement ();
      Object obj = decodeEngine.decodeElement (parentNS, parentTag, elm, parentObj);

      decodeEngine.cleanup ();

      return obj;
    }
    catch (CookXmlException ex)
    {
      // avoid handling the same exception twice
      throw ex;
    }
    catch (Exception ex)
    {
      getExceptionHandler ().handleException (null, ex);
    }
    return null;
  }

  /**
   * Gets the root object associated with the xml document root element.
   *
   * @return the object to be associated with.
   */
  public Object getRootObject ()
  {
    return m_rootObj;
  }

  /**
   * Sets the root object associated with the xml document root element.
   *
   * @param rootObj the object to be associated with.
   */
  public void setRootObject (Object rootObj)
  {
    m_rootObj = rootObj;
  }

  /**
   * Gets the DocumentBuilder used by this CookXml object.
   *
   * @return the DocumentBuilder used by this CookXml object.
   */
  public DocumentBuilder getDocumentBuilder ()
  {
    return m_docBuilder;
  }

  /**
   * sets the DocumentBuilder used by this CookXml object.
   *
   * @param docBuilder the DocumentBuilder to be used by this CookXml object.
   */
  public void setDocumentBuilder (DocumentBuilder docBuilder)
  {
    m_docBuilder = docBuilder;
  }

  /**
   * Gets the resource bundle used by this CookXml object.
   *
   * @return the resource bundle used by the xml document.
   */
  public ResourceBundle getResourceBundle ()
  {
    return m_bundle;
  }

  /**
   * Sets the resource bundle to be used by this CookXml object.
   *
   * @param bundle the resource bundle to be used by the xml document.
   */
  public void setResourceBundle (ResourceBundle bundle)
  {
    m_bundle = bundle;
  }
 
  public StringHook getUserStringHook() {
    return m_userhook;
  }
 
  public void setUserStringHook(StringHook hook) {
    m_userhook = hook;
  }

  /**
   * returns the current VarLookup object.
   * @return  the current VarLookup object.
   * @since CookXml 2.0
   */
  public VarLookup getVarLookup ()
  {
    return m_varLookup;
  }

  /**
   * sets the current VarLookup object.
   * @param  varLookup
   *      the VarLookup object which is used for variable lookup.
   * @since CookXml 2.0
   */
  public void setVarLookup (VarLookup varLookup)
  {
    m_varLookup = varLookup;
  }

  /**
   * returns the current ExceptionHandler.
   * @return  the current ExceptionHandler.
   * @since CookXml 2.0
   */
  public ExceptionHandler getExceptionHandler ()
  {
    ExceptionHandler handler = m_exceptionHandler;
    if (handler == null)
      return getDefaultExceptionHandler ();
    return handler;
  }

  /**
   * sets the current ExceptionHandler.
   * @param  exceptionHandler
   *      the handler for exceptions.
   * @since CookXml 2.0
   */
  public void setExceptionHandler (ExceptionHandler exceptionHandler)
  {
    m_exceptionHandler = exceptionHandler;
  }

  /**
   * Returns if CookXml should attempt to access non-public variables.
   * @return  if CookXml should attempt to access non-public variables
   * @since CookXml 2.3
   */
  public boolean isAccessible ()
  {
    return m_accessible;
  }

  /**
   * Setting this flag to true to allow this CookXml object to read/write
   * non-public variables (including package scope, protected, and private
   * variables).
   * <p>
   * Note, reading/writing non-public variable should be avoided for Web Start
   * applications or applications that run in a sandbox, as such action can
   * generate a SecurityException.
   * <p>
   * Usually, it is rather rare to have frequent access to a single variable.
   * So, performance-wise should be okay.  If you read/write a particular
   * variable more often, consider to cache the object.
   *
   * @see cookxml.core.exception.AccessException
   * @param   accessible  if CookXml should attempt to access non-public variables
   * @since CookXml 2.3
   */
  public void setAccessible (boolean accessible)
  {
    m_accessible = accessible;
  }

  /**
   * Obtain the ClassLoader that is used to locate resources.
   * @return  the default ClassLoader
   * @since CookXml 2.4
   */
  public ClassLoader getClassLoader ()
  {
    return m_classLoader;
  }

  /**
   * Set the ClassLaoder that is used to locate resouces.
   * @param   classLoader  the ClassLoader to be used.
   * @since CookXml 2.4
   */
  public void setClassLoader (ClassLoader classLoader)
  {
    m_classLoader = classLoader;
  }
}
TOP

Related Classes of cookxml.core.CookXml

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.