All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.org.apache.xalan.internal.client.XSLTProcessorApplet Maven / Gradle / Ivy

The newest version!
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 *
 *
 * This file incorporates work covered by the following copyright and
 * permission notice:
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * $Id: XSLTProcessorApplet.java,v 1.11 2010-11-01 04:34:10 joehw Exp $
 */
package com.sun.org.apache.xalan.internal.client;

import java.applet.Applet;
import java.awt.Graphics;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Hashtable;
import java.util.Enumeration;

import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import com.sun.org.apache.xalan.internal.res.XSLMessages;
import com.sun.org.apache.xalan.internal.res.XSLTErrorResources;

/**
 * Provides applet host for the XSLT processor. To perform transformations on an HTML client:
 * 
    *
  1. Use an <applet> tag to embed this applet in the HTML client.
  2. *
  3. Use the DocumentURL and StyleURL PARAM tags or the {@link #setDocumentURL} and * {@link #setStyleURL} methods to specify the XML source document and XSL stylesheet.
  4. *
  5. Call the {@link #getHtmlText} method (or one of the transformToHtml() methods) * to perform the transformation and return the result as a String.
  6. *
* * This class extends Applet which ultimately causes this class to implement Serializable. * This is a serious restriction on this class. All fields that are not transient and not * static are written-out/read-in during serialization. So even private fields essentially * become part of the API. Developers need to take care when modifying fields. * @xsl.usage general */ public class XSLTProcessorApplet extends Applet { /** * The stylesheet processor. * This field is now transient because a * javax.xml.transform.TransformerFactory from JAXP * makes no claims to be serializable. */ transient TransformerFactory m_tfactory = null; /** * @serial */ private String m_styleURL; /** * @serial */ private String m_documentURL; // Parameter names. To change a name of a parameter, you need only make // a single change. Simply modify the value of the parameter string below. //-------------------------------------------------------------------------- /** * @serial */ private final String PARAM_styleURL = "styleURL"; /** * @serial */ private final String PARAM_documentURL = "documentURL"; // We'll keep the DOM trees around, so tell which trees // are cached. /** * @serial */ private String m_styleURLOfCached = null; /** * @serial */ private String m_documentURLOfCached = null; /** * Save this for use on the worker thread; may not be necessary. * @serial */ private URL m_codeBase = null; /** * @serial */ private String m_treeURL = null; /** * DocumentBase URL * @serial */ private URL m_documentBase = null; /** * Thread stuff for the trusted worker thread. */ transient private Thread m_callThread = null; /** */ transient private TrustedAgent m_trustedAgent = null; /** * Thread for running TrustedAgent. */ transient private Thread m_trustedWorker = null; /** * Where the worker thread puts the HTML text. */ transient private String m_htmlText = null; /** * Where the worker thread puts the document/stylesheet text. */ transient private String m_sourceText = null; /** * Stylesheet attribute name and value that the caller can set. */ transient private String m_nameOfIDAttrOfElemToModify = null; /** */ transient private String m_elemIdToModify = null; /** */ transient private String m_attrNameToSet = null; /** */ transient private String m_attrValueToSet = null; /** * The XSLTProcessorApplet constructor takes no arguments. */ public XSLTProcessorApplet(){} /** * Get basic information about the applet * @return A String with the applet name and author. */ public String getAppletInfo() { return "Name: XSLTProcessorApplet\r\n" + "Author: Scott Boag"; } /** * Get descriptions of the applet parameters. * @return A two-dimensional array of Strings with Name, Type, and Description * for each parameter. */ public String[][] getParameterInfo() { String[][] info = { { PARAM_styleURL, "String", "URL to an XSL stylesheet" }, { PARAM_documentURL, "String", "URL to an XML document" }, }; return info; } /** * Standard applet initialization. */ public void init() { // PARAMETER SUPPORT // The following code retrieves the value of each parameter // specified with the tag and stores it in a member // variable. //---------------------------------------------------------------------- String param; // styleURL: Parameter description //---------------------------------------------------------------------- param = getParameter(PARAM_styleURL); // stylesheet parameters m_parameters = new Hashtable(); if (param != null) setStyleURL(param); // documentURL: Parameter description //---------------------------------------------------------------------- param = getParameter(PARAM_documentURL); if (param != null) setDocumentURL(param); m_codeBase = this.getCodeBase(); m_documentBase = this.getDocumentBase(); // If you use a ResourceWizard-generated "control creator" class to // arrange controls in your applet, you may want to call its // CreateControls() method from within this method. Remove the following // call to resize() before adding the call to CreateControls(); // CreateControls() does its own resizing. //---------------------------------------------------------------------- resize(320, 240); } /** * Automatically called when the HTML client containing the applet loads. * This method starts execution of the applet thread. */ public void start() { if (!securityCheck()) { throw new SecurityException("The XSLTProcessorApplet class must be extended and its methods start() overridden."); } m_trustedAgent = new TrustedAgent(); Thread currentThread = Thread.currentThread(); m_trustedWorker = new Thread(currentThread.getThreadGroup(), m_trustedAgent); m_trustedWorker.start(); try { m_tfactory = TransformerFactory.newInstance(); this.showStatus("Causing Transformer and Parser to Load and JIT..."); // Prime the pump so that subsequent transforms are faster. StringReader xmlbuf = new StringReader(""); StringReader xslbuf = new StringReader( ""); PrintWriter pw = new PrintWriter(new StringWriter()); synchronized (m_tfactory) { Templates templates = m_tfactory.newTemplates(new StreamSource(xslbuf)); Transformer transformer = templates.newTransformer(); transformer.transform(new StreamSource(xmlbuf), new StreamResult(pw)); } System.out.println("Primed the pump!"); this.showStatus("Ready to go!"); } catch (Exception e) { this.showStatus("Could not prime the pump!"); System.out.println("Could not prime the pump!"); e.printStackTrace(); } } /** * Do not call; this applet contains no UI or visual components. * */ public void paint(Graphics g){} /** * Automatically called when the HTML page containing the applet is no longer * on the screen. Stops execution of the applet thread. */ public void stop() { if (null != m_trustedWorker) { m_trustedWorker.stop(); // m_trustedWorker.destroy(); m_trustedWorker = null; } m_styleURLOfCached = null; m_documentURLOfCached = null; } /** * Cleanup; called when applet is terminated and unloaded. */ public void destroy() { if (null != m_trustedWorker) { m_trustedWorker.stop(); // m_trustedWorker.destroy(); m_trustedWorker = null; } m_styleURLOfCached = null; m_documentURLOfCached = null; } /** * Set the URL to the XSL stylesheet that will be used * to transform the input XML. No processing is done yet. * @param urlString valid URL string for XSL stylesheet. */ public void setStyleURL(String urlString) { m_styleURL = urlString; } /** * Set the URL to the XML document that will be transformed * with the XSL stylesheet. No processing is done yet. * @param urlString valid URL string for XML document. */ public void setDocumentURL(String urlString) { m_documentURL = urlString; } /** * The processor keeps a cache of the source and * style trees, so call this method if they have changed * or you want to do garbage collection. */ public void freeCache() { m_styleURLOfCached = null; m_documentURLOfCached = null; } /** * Set an attribute in the stylesheet, which gives the ability * to have some dynamic selection control. * @param nameOfIDAttrOfElemToModify The name of an attribute to search for a unique id. * @param elemId The unique ID to look for. * @param attrName Once the element is found, the name of the attribute to set. * @param value The value to set the attribute to. */ public void setStyleSheetAttribute(String nameOfIDAttrOfElemToModify, String elemId, String attrName, String value) { m_nameOfIDAttrOfElemToModify = nameOfIDAttrOfElemToModify; m_elemIdToModify = elemId; m_attrNameToSet = attrName; m_attrValueToSet = value; } /** * Stylesheet parameter key/value pair stored in a hashtable */ transient Hashtable m_parameters; /** * Submit a stylesheet parameter. * * @param key stylesheet parameter key * @param expr the parameter expression to be submitted. * @see javax.xml.transform.Transformer#setParameter(String,Object) */ public void setStylesheetParam(String key, String expr) { m_parameters.put(key, expr); } /** * Given a String containing markup, escape the markup so it * can be displayed in the browser. * * @param s String to escape * * The escaped string. */ public String escapeString(String s) { StringBuffer sb = new StringBuffer(); int length = s.length(); for (int i = 0; i < length; i++) { char ch = s.charAt(i); if ('<' == ch) { sb.append("<"); } else if ('>' == ch) { sb.append(">"); } else if ('&' == ch) { sb.append("&"); } else if (0xd800 <= ch && ch < 0xdc00) { // UTF-16 surrogate int next; if (i + 1 >= length) { throw new RuntimeException( XSLMessages.createMessage( XSLTErrorResources.ER_INVALID_UTF16_SURROGATE, new Object[]{ Integer.toHexString(ch) })); //"Invalid UTF-16 surrogate detected: " //+Integer.toHexString(ch)+ " ?"); } else { next = s.charAt(++i); if (!(0xdc00 <= next && next < 0xe000)) throw new RuntimeException( XSLMessages.createMessage( XSLTErrorResources.ER_INVALID_UTF16_SURROGATE, new Object[]{ Integer.toHexString(ch) + " " + Integer.toHexString(next) })); //"Invalid UTF-16 surrogate detected: " //+Integer.toHexString(ch)+" "+Integer.toHexString(next)); next = ((ch - 0xd800) << 10) + next - 0xdc00 + 0x00010000; } sb.append("&#x"); sb.append(Integer.toHexString(next)); sb.append(";"); } else { sb.append(ch); } } return sb.toString(); } /** * Assuming the stylesheet URL and the input XML URL have been set, * perform the transformation and return the result as a String. * * @return A string that contains the contents pointed to by the URL. * */ public String getHtmlText() { m_trustedAgent.m_getData = true; m_callThread = Thread.currentThread(); try { synchronized (m_callThread) { m_callThread.wait(); } } catch (InterruptedException ie) { System.out.println(ie.getMessage()); } return m_htmlText; } /** * Get an XML document (or stylesheet) * * @param treeURL valid URL string for the document. * * @return document * * @throws IOException */ public String getTreeAsText(String treeURL) throws IOException { m_treeURL = treeURL; m_trustedAgent.m_getData = true; m_trustedAgent.m_getSource = true; m_callThread = Thread.currentThread(); try { synchronized (m_callThread) { m_callThread.wait(); } } catch (InterruptedException ie) { System.out.println(ie.getMessage()); } return m_sourceText; } /** * Use a Transformer to copy the source document * to a StreamResult. * * @return the document as a string */ private String getSource() throws TransformerException { StringWriter osw = new StringWriter(); PrintWriter pw = new PrintWriter(osw, false); String text = ""; try { URL docURL = new URL(m_documentBase, m_treeURL); synchronized (m_tfactory) { Transformer transformer = m_tfactory.newTransformer(); StreamSource source = new StreamSource(docURL.toString()); StreamResult result = new StreamResult(pw); transformer.transform(source, result); text = osw.toString(); } } catch (MalformedURLException e) { e.printStackTrace(); throw new RuntimeException(e.getMessage()); } catch (Exception any_error) { any_error.printStackTrace(); } return text; } /** * Get the XML source Tree as a text string suitable * for display in a browser. Note that this is for display of the * XML itself, not for rendering of HTML by the browser. * * @return XML source document as a string. * @throws Exception thrown if tree can not be converted. */ public String getSourceTreeAsText() throws Exception { return getTreeAsText(m_documentURL); } /** * Get the XSL style Tree as a text string suitable * for display in a browser. Note that this is for display of the * XML itself, not for rendering of HTML by the browser. * * @return The XSL stylesheet as a string. * @throws Exception thrown if tree can not be converted. */ public String getStyleTreeAsText() throws Exception { return getTreeAsText(m_styleURL); } /** * Get the HTML result Tree as a text string suitable * for display in a browser. Note that this is for display of the * XML itself, not for rendering of HTML by the browser. * * @return Transformation result as unmarked text. * @throws Exception thrown if tree can not be converted. */ public String getResultTreeAsText() throws Exception { return escapeString(getHtmlText()); } /** * Process a document and a stylesheet and return * the transformation result. If one of these is null, the * existing value (of a previous transformation) is not affected. * * @param doc URL string to XML document * @param style URL string to XSL stylesheet * * @return HTML transformation result */ public String transformToHtml(String doc, String style) { if (null != doc) { m_documentURL = doc; } if (null != style) { m_styleURL = style; } return getHtmlText(); } /** * Process a document and a stylesheet and return * the transformation result. Use the xsl:stylesheet PI to find the * document, if one exists. * * @param doc URL string to XML document containing an xsl:stylesheet PI. * * @return HTML transformation result */ public String transformToHtml(String doc) { if (null != doc) { m_documentURL = doc; } m_styleURL = null; return getHtmlText(); } /** * Process the transformation. * * @return The transformation result as a string. * * @throws TransformerException */ private String processTransformation() throws TransformerException { String htmlData = null; this.showStatus("Waiting for Transformer and Parser to finish loading and JITing..."); synchronized (m_tfactory) { URL documentURL = null; URL styleURL = null; StringWriter osw = new StringWriter(); PrintWriter pw = new PrintWriter(osw, false); StreamResult result = new StreamResult(pw); this.showStatus("Begin Transformation..."); try { documentURL = new URL(m_codeBase, m_documentURL); StreamSource xmlSource = new StreamSource(documentURL.toString()); styleURL = new URL(m_codeBase, m_styleURL); StreamSource xslSource = new StreamSource(styleURL.toString()); Transformer transformer = m_tfactory.newTransformer(xslSource); Enumeration m_keys = m_parameters.keys(); while (m_keys.hasMoreElements()){ Object key = m_keys.nextElement(); Object expression = m_parameters.get(key); transformer.setParameter((String) key, expression); } transformer.transform(xmlSource, result); } catch (TransformerConfigurationException tfe) { tfe.printStackTrace(); throw new RuntimeException(tfe.getMessage()); } catch (MalformedURLException e) { e.printStackTrace(); throw new RuntimeException(e.getMessage()); } this.showStatus("Transformation Done!"); htmlData = osw.toString(); } return htmlData; } /** * This class maintains a worker thread that that is * trusted and can do things like access data. You need * this because the thread that is called by the browser * is not trusted and can't access data from the URLs. */ class TrustedAgent implements Runnable { /** * Specifies whether the worker thread should perform a transformation. */ public boolean m_getData = false; /** * Specifies whether the worker thread should get an XML document or XSL stylesheet. */ public boolean m_getSource = false; /** * The real work is done from here. * */ public void run() { if (!securityCheck()) { throw new SecurityException("The XSLTProcessorApplet class must be extended " + "and its method start() overridden. The result of the transformation " + "can be obtained by calling getHtmlText()."); } while (true) { m_trustedWorker.yield(); if (m_getData) // Perform a transformation or get a document. { try { m_getData = false; m_htmlText = null; m_sourceText = null; if (m_getSource) // Get a document. { m_getSource = false; m_sourceText = getSource(); } else // Perform a transformation. m_htmlText = processTransformation(); } catch (Exception e) { e.printStackTrace(); } finally { synchronized (m_callThread) { m_callThread.notify(); } } } else { try { m_trustedWorker.sleep(50); } catch (InterruptedException ie) { ie.printStackTrace(); } } } } } // For compatiblity with old serialized objects // We will change non-serialized fields and change methods // and not have this break us. private static final long serialVersionUID=4618876841979251422L; // For compatibility when de-serializing old objects private void readObject(java.io.ObjectInputStream inStream) throws IOException, ClassNotFoundException { inStream.defaultReadObject(); // Needed assignment of non-serialized fields // A TransformerFactory is not guaranteed to be serializable, // so we create one here m_tfactory = TransformerFactory.newInstance(); } private boolean securityCheck() { //check if user code's on the stack before invoking the worker thread boolean passed = false; try { java.security.AccessController.checkPermission(new java.security.AllPermission()); } catch (SecurityException se) { //expected passed = true; } return passed; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy