Package org.apache.xalan.xslt

Source Code of org.apache.xalan.xslt.ExtensionNSHandler$ExtErrorHandler

/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999 The Apache Software Foundation.  All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
*
* 3. The end-user documentation included with the redistribution,
*    if any, must include the following acknowledgment:
*       "This product includes software developed by the
*        Apache Software Foundation (http://www.apache.org/)."
*    Alternately, this acknowledgment may appear in the software itself,
*    if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xalan" and "Apache Software Foundation" must
*    not be used to endorse or promote products derived from this
*    software without prior written permission. For written
*    permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
*    nor may "Apache" appear in their name, without prior written
*    permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 1999, Lotus
* Development Corporation., http://www.lotus.com.  For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.xalan.xslt;

import java.util.*;
import java.io.*;
import java.net.*;

import org.w3c.dom.*;
import org.xml.sax.*;
import org.apache.xalan.xpath.xml.QName;

import org.apache.xalan.xpath.ExtensionFunctionHandler;
import org.apache.xalan.xpath.XPathProcessorException;

/**
* <meta name="usage" content="advanced"/>
* Represents an extension namespace. Provides functions
* to call into the extension via both element syntax and function
* syntax. Extends XPath's extension function capability to a full
* namespace extension model.
*
* @author Sanjiva Weerawarana (sanjiva@watson.ibm.com)
*/
public class ExtensionNSHandler extends ExtensionFunctionHandler implements Serializable
{
  transient XSLTEngineImpl xslp;        // xsl processor for whom I'm working
  Hashtable elements = new Hashtable (); // ext. elements of this namespace
  boolean componentDescLoaded; // true when info from the component desc
  // has been loaded. This gets set as soon
  // as any of the info has been specified.
  // If this is false, when processElement or
  // processFunction is called it will use the
  // namespace URI as a URL and try to load
  // that location as the component desc.

  /////////////////////////////////////////////////////////////////////////
  // Constructors
  /////////////////////////////////////////////////////////////////////////

  /**
   * Construct a new extension namespace handler for a given extension NS.
   * This doesn't do anything - just hang on to the namespace URI.
   *
   * @param xslp         handle to the XSL processor that I'm working for
   * @param namespaceUri the extension namespace URI that I'm implementing
   */
  public ExtensionNSHandler (XSLTEngineImpl xslp, String namespaceUri)
  {
    super (namespaceUri);
    this.xslp = xslp;
  }

  /////////////////////////////////////////////////////////////////////////

  /**
   * Construct a new extension namespace handler given all the information
   * needed.
   *
   * @param xslp         handle to the XSL processor that I'm working for
   * @param namespaceUri the extension namespace URI that I'm implementing
   * @param elemNames    string containing list of elements of extension NS
   * @param funcNames    string containing list of functions of extension NS
   * @param lang         language of code implementing the extension
   * @param srcURL       value of src attribute (if any) - treated as a URL
   *                     or a classname depending on the value of lang. If
   *                     srcURL is not null, then scriptSrc is ignored.
   * @param scriptSrc    the actual script code (if any)
   */
  public ExtensionNSHandler (XSLTEngineImpl xslp, String namespaceUri,
                             String elemNames, String funcNames,
                             String lang, String srcURL, String src)
  {
    super (namespaceUri, funcNames, lang, srcURL, src);
    this.xslp = xslp;
    setElements (elemNames);
    componentDescLoaded = true;
  }

  /////////////////////////////////////////////////////////////////////////
  // Main API
  /////////////////////////////////////////////////////////////////////////

  /*
  * Set function local parts of extension NS. Super does the work; I
  * just record that a component desc has been loaded.
  *
  * @param functions whitespace separated list of function names defined
  *        by this extension namespace.
  */
  public void setFunctions (String funcNames)
  {
    super.setFunctions (funcNames);
    componentDescLoaded = true;
  }

  /////////////////////////////////////////////////////////////////////////

  /**
   * Set the script data for this extension NS. Deferred to super for
   * actual work - I only record that a component desc has been loaded.
   *
   * @param lang      language of the script.
   * @param srcURL    value of src attribute (if any) - treated as a URL
   *                  or a classname depending on the value of lang. If
   *                  srcURL is not null, then scriptSrc is ignored.
   * @param scriptSrc the actual script code (if any)
   */
  public void setScript (String lang, String srcURL, String scriptSrc)
  {
    super.setScript (lang, srcURL, scriptSrc);
    componentDescLoaded = true;
  }

  /////////////////////////////////////////////////////////////////////////

  /**
   * Set element local parts of extension NS.
   *
   * @param elemNames whitespace separated list of element names defined
   *        by this extension namespace.
   */
  public void setElements (String elemNames)
  {
    if (elemNames == null)
    {
      return;
    }
    StringTokenizer st = new StringTokenizer (elemNames, " \t\n\r", false);
    Object junk = new Object ();
    while (st.hasMoreTokens ())
    {
      String tok = st.nextToken ();
      elements.put (tok, junk); // just stick it in there basically
    }
    componentDescLoaded = true;
  }

  /////////////////////////////////////////////////////////////////////////

  /**
   * Tests whether a certain element name is known within this namespace.
   *
   * @param element name of the element being tested
   *
   * @return true if its known, false if not.
   */
  public boolean isElementAvailable (String element)
  {
    return (elements.get (element) != null);
  }

  /////////////////////////////////////////////////////////////////////////

  /**
   * Process a call to this extension namespace via an element. As a side
   * effect, the results are sent to the XSLTEngineImpl's result tree.
   *
   * @param localPart      Element name's local part.
   * @param element        The extension element being processed.
   * @param processor      Handle to XSLTEngineImpl.
   * @param stylesheetTree The compiled stylesheet tree.
   * @param mode           The current mode.
   * @param sourceTree     The root of the source tree (but don't assume
   *                       it's a Document).
   * @param sourceNode     The current context node.
   *
   * @exception XSLProcessorException thrown if something goes wrong
   *            while running the extension handler.
   * @exception MalformedURLException if loading trouble
   * @exception FileNotFoundException if loading trouble
   * @exception IOException           if loading trouble
   * @exception SAXException          if parsing trouble
   */
  public void processElement (String localPart, Element element,
                              XSLTEngineImpl processor,
                              Stylesheet stylesheetTree,
                              Node sourceTree, Node sourceNode, QName mode,
                              Class classObj, Object methodKey)
    throws XSLProcessorException,
           MalformedURLException,
           FileNotFoundException,
           IOException,
           SAXException
  {
    if (!componentStarted)
    {
      try
      {
        startupComponent (classObj);
      }
      catch (XPathProcessorException e)
      {
        // e.printStackTrace ();
        throw new XSLProcessorException (e.getMessage (), e);
      }
    }

    Object result = null;
    try
    {
      XSLProcessorContext xpc =
                               new XSLProcessorContext (processor, stylesheetTree,
                                                        sourceTree, sourceNode, mode);
      Vector argv = new Vector (2);
      argv.addElement (xpc);
      argv.addElement (element);
      result = super.callFunction (localPart, argv, methodKey, classObj);
    }
    catch (XPathProcessorException e)
    {
      // e.printStackTrace ();
      throw new XSLProcessorException (e.getMessage (), e);
    }

    if (result != null)
    {
      processor.outputToResultTree (stylesheetTree, result);
    }
  }

  /////////////////////////////////////////////////////////////////////////
  // Private/Protected Functions
  /////////////////////////////////////////////////////////////////////////

  /**
   * Start the component up by executing any script that needs to run
   * at startup time. This needs to happen before any functions can be
   * called on the component.
   *
   * @exception XPathProcessorException if something bad happens.
   */
  protected void startupComponent (Class classObj) throws  XPathProcessorException
  {
    if(!bsfInitialized)
    {
      synchronized(com.ibm.bsf.BSFManager.class)
      {
        bsfInitialized = true;
        com.ibm.bsf.BSFManager.registerScriptingEngine ("xslt-javaclass",
                                                        "org.apache.xalan.xpath.XSLTJavaClassEngine",
                                                        new String[0]);
      }
    }

    if (!componentDescLoaded)
    {
      try
      {
        loadComponentDescription ();
      }
      catch (Exception e)
      {
        throw new XPathProcessorException (e.getMessage (), e);
      }
    }
    super.startupComponent (classObj);
  }

  /////////////////////////////////////////////////////////////////////////

  /**
   * Load the component spec for this extension namespace taking the URI
   * of this namespace as the URL to read from.
   *
   * @exception XSLProcessorException if something bad happens.
   * @exception MalformedURLException if loading trouble
   * @exception FileNotFoundException if loading trouble
   * @exception IOException           if loading trouble
   * @exception SAXException          if parsing trouble
   */
  private void loadComponentDescription ()
    throws  XSLProcessorException,
    MalformedURLException,
    FileNotFoundException,
    IOException,
    SAXException
  {
    // first try treaing the URI of the extension as a fully qualified
    // class name; if it works then go with treating this an extension
    // implemented in "javaclass" for with that class being the srcURL.
    // forget about setting elements and functions in that case - so if
    // u do extension-{element,function}-available then u get false,
    // but that's ok.
    try {
      String cname = namespaceUri.startsWith ("class:") ?
                       namespaceUri.substring (6) : namespaceUri;
      Class.forName (cname); // does it load?
      setScript ("javaclass", namespaceUri, null);
      componentDescLoaded = true;
      return;
    } catch (Exception e) {
      // oops, it failed .. ok, so this path ain't gonna pan out. shucks.
    }

    // parse the document at the URI of the extension, if any
    URL url = xslp.getURLFromString(namespaceUri,
                                    xslp.m_stylesheetRoot.m_baseIdent);
    // System.out.println("Extension URI: "+url.toString());
    org.apache.xalan.xpath.xml.XMLParserLiaison liaison = xslp.m_parserLiaison;
    if(liaison instanceof org.apache.xalan.xpath.dtm.DTMLiaison)
    {
      // There ought to be a better way.  At least if we know we
      // have the DTM, we ought to have Xerces.
      liaison = new org.apache.xalan.xpath.xdom.XercesLiaison();
      liaison.setErrorHandler(new ExtErrorHandler(url.toString()));
    }
    Element componentElement = null;
    /*
    try
    {
    */
    liaison.parse(new InputSource(url.toString()));
    Document compSpec = liaison.getDocument();
    componentElement = compSpec.getDocumentElement ();

    // determine the functions and elements of this component
    setElements (componentElement.getAttribute ("elements"));
    setFunctions (componentElement.getAttribute ("functions"));

    // is there an lxslt:script element child? [NOTE THAT THIS IS NOT
    // PROPER NAMESPACE-WISE .. I'll FIX IT LATER. .. Sanjiva 8/20/99.]
    NodeList nl = componentElement.getElementsByTagName ("lxslt:script");
    switch (nl.getLength ())
    {
    case 0:
      break;
    case 1:
      Element scriptElem = (Element) nl.item (0);
      String lang = scriptElem.getAttribute ("lang");
      Attr srcURLAttr = scriptElem.getAttributeNode ("src");
      String srcURL = (srcURLAttr == null) ? null : srcURLAttr.getValue ();
      String src = getScriptString (scriptElem);
      setScript (lang, srcURL, src);
      break;
    default:
      throw new XSLProcessorException ("too many <script>s in component");
    }
    componentDescLoaded = true;
    /*
    }
    catch(org.xml.sax.SAXException se)
    {

    }
    catch(java.net.UnknownHostException uhe)
    {

    }
    */
  }

  /////////////////////////////////////////////////////////////////////////

  /**
   * extract the text nodes and CDATA content children of the given
   * elem and return as a string. Any other types of node children
   * are ignored
   *
   * @param elem element whose text and cdata children are to be
   *        concatenated together.
   *
   * @return string resulting from concatanating the text/cdata child
   *         nodes' values.
   */
  private String getScriptString (Element elem)
  {
    StringBuffer strBuf = new StringBuffer();
    for (Node n = elem.getFirstChild (); n != null; n = n.getNextSibling ())
    {
      switch (n.getNodeType())
      {
      case Node.TEXT_NODE:
      case Node.CDATA_SECTION_NODE:
        strBuf.append(((CharacterData) n).getData());
        break;
      default:
        break;
      }
    }
    return strBuf.toString();
  }


  /**
   * Implement SAX error handler for default reporting.
   */
  class ExtErrorHandler implements ErrorHandler
  {
    String m_xmlID = null;

    public ExtErrorHandler(String identifier)
    {
      m_xmlID = identifier;
    }

    /**
     * Receive notification of a warning.
     *
     * <p>SAX parsers will use this method to report conditions that
     * are not errors or fatal errors as defined by the XML 1.0
     * recommendation.  The default behaviour is to take no action.</p>
     *
     * <p>The SAX parser must continue to provide normal parsing events
     * after invoking this method: it should still be possible for the
     * application to process the document through to the end.</p>
     *
     * @param exception The warning information encapsulated in a
     *                  SAX parse exception.
     * @exception org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     * @see org.xml.sax.SAXParseException
     */
    public void warning (SAXParseException exception)
      throws SAXException
    {
      System.out.println("Parser warning: "+exception.getMessage());
    }


    /**
     * Receive notification of a recoverable error.
     *
     * <p>This corresponds to the definition of "error" in section 1.2
     * of the W3C XML 1.0 Recommendation.  For example, a validating
     * parser would use this callback to report the violation of a
     * validity constraint.  The default behaviour is to take no
     * action.</p>
     *
     * <p>The SAX parser must continue to provide normal parsing events
     * after invoking this method: it should still be possible for the
     * application to process the document through to the end.  If the
     * application cannot do so, then the parser should report a fatal
     * error even if the XML 1.0 recommendation does not require it to
     * do so.</p>
     *
     * @param exception The error information encapsulated in a
     *                  SAX parse exception.
     * @exception org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     * @see org.xml.sax.SAXParseException
     */
    public void error (SAXParseException exception)
      throws SAXException
    {
      System.out.println("Parser error: "+exception.getMessage());
    }

    /**
     * Receive notification of a non-recoverable error.
     *
     * <p>This corresponds to the definition of "fatal error" in
     * section 1.2 of the W3C XML 1.0 Recommendation.  For example, a
     * parser would use this callback to report the violation of a
     * well-formedness constraint.</p>
     *
     * <p>The application must assume that the document is unusable
     * after the parser has invoked this method, and should continue
     * (if at all) only for the sake of collecting addition error
     * messages: in fact, SAX parsers are free to stop reporting any
     * other events once this method has been invoked.</p>
     *
     * @param exception The error information encapsulated in a
     *                  SAX parse exception.
     * @exception org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     * @see org.xml.sax.SAXParseException
     */
    public void fatalError (SAXParseException exception)
      throws SAXException
    {
    }

  }

}
TOP

Related Classes of org.apache.xalan.xslt.ExtensionNSHandler$ExtErrorHandler

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.