jaxp/src/share/classes/com/sun/org/apache/xalan/internal/client/XSLTProcessorApplet.java
changeset 2834 9108d209bc43
parent 2833 97a4a96a6945
parent 2726 d60a9ce3c3ea
child 2835 3025d4f48799
equal deleted inserted replaced
2833:97a4a96a6945 2834:9108d209bc43
     1 /*
       
     2  * reserved comment block
       
     3  * DO NOT REMOVE OR ALTER!
       
     4  */
       
     5 /*
       
     6  * Copyright 1999-2004 The Apache Software Foundation.
       
     7  *
       
     8  * Licensed under the Apache License, Version 2.0 (the "License");
       
     9  * you may not use this file except in compliance with the License.
       
    10  * You may obtain a copy of the License at
       
    11  *
       
    12  *     http://www.apache.org/licenses/LICENSE-2.0
       
    13  *
       
    14  * Unless required by applicable law or agreed to in writing, software
       
    15  * distributed under the License is distributed on an "AS IS" BASIS,
       
    16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    17  * See the License for the specific language governing permissions and
       
    18  * limitations under the License.
       
    19  */
       
    20 /*
       
    21  * $Id: XSLTProcessorApplet.java,v 1.2.4.1 2005/09/15 02:20:05 jeffsuttor Exp $
       
    22  */
       
    23 package com.sun.org.apache.xalan.internal.client;
       
    24 
       
    25 import java.applet.Applet;
       
    26 import java.awt.Graphics;
       
    27 import java.io.IOException;
       
    28 import java.io.PrintWriter;
       
    29 import java.io.StringReader;
       
    30 import java.io.StringWriter;
       
    31 import java.net.MalformedURLException;
       
    32 import java.net.URL;
       
    33 import java.util.Hashtable;
       
    34 import java.util.Enumeration;
       
    35 
       
    36 import javax.xml.transform.Templates;
       
    37 import javax.xml.transform.Transformer;
       
    38 import javax.xml.transform.TransformerConfigurationException;
       
    39 import javax.xml.transform.TransformerException;
       
    40 import javax.xml.transform.TransformerFactory;
       
    41 import javax.xml.transform.stream.StreamResult;
       
    42 import javax.xml.transform.stream.StreamSource;
       
    43 
       
    44 import com.sun.org.apache.xalan.internal.res.XSLMessages;
       
    45 import com.sun.org.apache.xalan.internal.res.XSLTErrorResources;
       
    46 
       
    47 /**
       
    48  * Provides applet host for the XSLT processor. To perform transformations on an HTML client:
       
    49  * <ol>
       
    50  * <li>Use an &lt;applet&gt; tag to embed this applet in the HTML client.</li>
       
    51  * <li>Use the DocumentURL and StyleURL PARAM tags or the {@link #setDocumentURL} and
       
    52  * {@link #setStyleURL} methods to specify the XML source document and XSL stylesheet.</li>
       
    53  * <li>Call the {@link #getHtmlText} method (or one of the transformToHtml() methods)
       
    54  * to perform the transformation and return the result as a String.</li>
       
    55  * </ol>
       
    56  *
       
    57  * This class extends Applet which ultimately causes this class to implement Serializable.
       
    58  * This is a serious restriction on this class. All fields that are not transient and not
       
    59  * static are written-out/read-in during serialization. So even private fields essentially
       
    60  * become part of the API. Developers need to take care when modifying fields.
       
    61  * @xsl.usage general
       
    62  */
       
    63 public class XSLTProcessorApplet extends Applet
       
    64 {
       
    65 
       
    66   /**
       
    67    * The stylesheet processor.
       
    68    * This field is now transient because a
       
    69    * javax.xml.transform.TransformerFactory from JAXP
       
    70    * makes no claims to be serializable.
       
    71    */
       
    72   transient TransformerFactory m_tfactory = null;
       
    73 
       
    74   /**
       
    75    * @serial
       
    76    */
       
    77   private String m_styleURL;
       
    78 
       
    79   /**
       
    80    * @serial
       
    81    */
       
    82   private String m_documentURL;
       
    83 
       
    84   // Parameter names.  To change a name of a parameter, you need only make
       
    85   // a single change.  Simply modify the value of the parameter string below.
       
    86   //--------------------------------------------------------------------------
       
    87 
       
    88   /**
       
    89    * @serial
       
    90    */
       
    91   private final String PARAM_styleURL = "styleURL";
       
    92 
       
    93   /**
       
    94    * @serial
       
    95    */
       
    96   private final String PARAM_documentURL = "documentURL";
       
    97 
       
    98 
       
    99   // We'll keep the DOM trees around, so tell which trees
       
   100   // are cached.
       
   101 
       
   102   /**
       
   103    * @serial
       
   104    */
       
   105   private String m_styleURLOfCached = null;
       
   106 
       
   107   /**
       
   108    * @serial
       
   109    */
       
   110   private String m_documentURLOfCached = null;
       
   111 
       
   112   /**
       
   113    * Save this for use on the worker thread; may not be necessary.
       
   114    * @serial
       
   115    */
       
   116   private URL m_codeBase = null;
       
   117 
       
   118   /**
       
   119    * @serial
       
   120    */
       
   121   private String m_treeURL = null;
       
   122 
       
   123   /**
       
   124    * DocumentBase URL
       
   125    * @serial
       
   126    */
       
   127   private URL m_documentBase = null;
       
   128 
       
   129   /**
       
   130    * Thread stuff for the trusted worker thread.
       
   131    */
       
   132   transient private Thread m_callThread = null;
       
   133 
       
   134   /**
       
   135    */
       
   136   transient private TrustedAgent m_trustedAgent = null;
       
   137 
       
   138   /**
       
   139    * Thread for running TrustedAgent.
       
   140    */
       
   141   transient private Thread m_trustedWorker = null;
       
   142 
       
   143   /**
       
   144    * Where the worker thread puts the HTML text.
       
   145    */
       
   146   transient private String m_htmlText = null;
       
   147 
       
   148   /**
       
   149    * Where the worker thread puts the document/stylesheet text.
       
   150    */
       
   151   transient private String m_sourceText = null;
       
   152 
       
   153   /**
       
   154    * Stylesheet attribute name and value that the caller can set.
       
   155    */
       
   156   transient private String m_nameOfIDAttrOfElemToModify = null;
       
   157 
       
   158   /**
       
   159    */
       
   160   transient private String m_elemIdToModify = null;
       
   161 
       
   162   /**
       
   163    */
       
   164   transient private String m_attrNameToSet = null;
       
   165 
       
   166   /**
       
   167    */
       
   168   transient private String m_attrValueToSet = null;
       
   169 
       
   170   /**
       
   171    * The XSLTProcessorApplet constructor takes no arguments.
       
   172    */
       
   173   public XSLTProcessorApplet(){}
       
   174 
       
   175   /**
       
   176    * Get basic information about the applet
       
   177    * @return A String with the applet name and author.
       
   178    */
       
   179   public String getAppletInfo()
       
   180   {
       
   181     return "Name: XSLTProcessorApplet\r\n" + "Author: Scott Boag";
       
   182   }
       
   183 
       
   184   /**
       
   185    * Get descriptions of the applet parameters.
       
   186    * @return A two-dimensional array of Strings with Name, Type, and Description
       
   187    * for each parameter.
       
   188    */
       
   189   public String[][] getParameterInfo()
       
   190   {
       
   191 
       
   192     String[][] info =
       
   193     {
       
   194       { PARAM_styleURL, "String", "URL to an XSL stylesheet" },
       
   195       { PARAM_documentURL, "String", "URL to an XML document" },
       
   196     };
       
   197 
       
   198     return info;
       
   199   }
       
   200 
       
   201   /**
       
   202    * Standard applet initialization.
       
   203    */
       
   204   public void init()
       
   205   {
       
   206 
       
   207     // PARAMETER SUPPORT
       
   208     //          The following code retrieves the value of each parameter
       
   209     // specified with the <PARAM> tag and stores it in a member
       
   210     // variable.
       
   211     //----------------------------------------------------------------------
       
   212     String param;
       
   213 
       
   214     // styleURL: Parameter description
       
   215     //----------------------------------------------------------------------
       
   216     param = getParameter(PARAM_styleURL);
       
   217 
       
   218     // stylesheet parameters
       
   219     m_parameters = new Hashtable();
       
   220 
       
   221     if (param != null)
       
   222       setStyleURL(param);
       
   223 
       
   224     // documentURL: Parameter description
       
   225     //----------------------------------------------------------------------
       
   226     param = getParameter(PARAM_documentURL);
       
   227 
       
   228     if (param != null)
       
   229       setDocumentURL(param);
       
   230 
       
   231     m_codeBase = this.getCodeBase();
       
   232     m_documentBase = this.getDocumentBase();
       
   233 
       
   234     // If you use a ResourceWizard-generated "control creator" class to
       
   235     // arrange controls in your applet, you may want to call its
       
   236     // CreateControls() method from within this method. Remove the following
       
   237     // call to resize() before adding the call to CreateControls();
       
   238     // CreateControls() does its own resizing.
       
   239     //----------------------------------------------------------------------
       
   240     resize(320, 240);
       
   241   }
       
   242 
       
   243     /**
       
   244    *  Automatically called when the HTML client containing the applet loads.
       
   245    *  This method starts execution of the applet thread.
       
   246    */
       
   247   public void start()
       
   248   {
       
   249       //check if user code's on the stack before invoking the worker thread
       
   250      boolean passed = false;
       
   251      try {
       
   252        java.security.AccessController.checkPermission(new java.security.AllPermission());
       
   253      } catch (SecurityException se) {
       
   254          //expected
       
   255          passed = true;
       
   256      }
       
   257      if (!passed) {
       
   258          throw new SecurityException("The XSLTProcessorApplet class must be extended and its method start() overridden.");
       
   259      }
       
   260 
       
   261     m_trustedAgent = new TrustedAgent();
       
   262     Thread currentThread = Thread.currentThread();
       
   263     m_trustedWorker = new Thread(currentThread.getThreadGroup(),
       
   264                                  m_trustedAgent);
       
   265     m_trustedWorker.start();
       
   266     try
       
   267     {
       
   268       m_tfactory = TransformerFactory.newInstance();
       
   269       this.showStatus("Causing Transformer and Parser to Load and JIT...");
       
   270 
       
   271       // Prime the pump so that subsequent transforms are faster.
       
   272       StringReader xmlbuf = new StringReader("<?xml version='1.0'?><foo/>");
       
   273       StringReader xslbuf = new StringReader(
       
   274         "<?xml version='1.0'?><xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'><xsl:template match='foo'><out/></xsl:template></xsl:stylesheet>");
       
   275       PrintWriter pw = new PrintWriter(new StringWriter());
       
   276 
       
   277       synchronized (m_tfactory)
       
   278       {
       
   279         Templates templates = m_tfactory.newTemplates(new StreamSource(xslbuf));
       
   280         Transformer transformer = templates.newTransformer();
       
   281         transformer.transform(new StreamSource(xmlbuf), new StreamResult(pw));
       
   282       }
       
   283       System.out.println("Primed the pump!");
       
   284       this.showStatus("Ready to go!");
       
   285     }
       
   286     catch (Exception e)
       
   287     {
       
   288       this.showStatus("Could not prime the pump!");
       
   289       System.out.println("Could not prime the pump!");
       
   290       e.printStackTrace();
       
   291     }
       
   292   }
       
   293 
       
   294   /**
       
   295    * Do not call; this applet contains no UI or visual components.
       
   296    *
       
   297    */
       
   298   public void paint(Graphics g){}
       
   299 
       
   300   /**
       
   301    * Automatically called when the HTML page containing the applet is no longer
       
   302    * on the screen. Stops execution of the applet thread.
       
   303    */
       
   304   public void stop()
       
   305   {
       
   306     if (null != m_trustedWorker)
       
   307     {
       
   308       m_trustedWorker.stop();
       
   309 
       
   310       // m_trustedWorker.destroy();
       
   311       m_trustedWorker = null;
       
   312     }
       
   313 
       
   314     m_styleURLOfCached = null;
       
   315     m_documentURLOfCached = null;
       
   316   }
       
   317 
       
   318   /**
       
   319    * Cleanup; called when applet is terminated and unloaded.
       
   320    */
       
   321   public void destroy()
       
   322   {
       
   323     if (null != m_trustedWorker)
       
   324     {
       
   325       m_trustedWorker.stop();
       
   326 
       
   327       // m_trustedWorker.destroy();
       
   328       m_trustedWorker = null;
       
   329     }
       
   330     m_styleURLOfCached = null;
       
   331     m_documentURLOfCached = null;
       
   332   }
       
   333 
       
   334   /**
       
   335    * Set the URL to the XSL stylesheet that will be used
       
   336    * to transform the input XML.  No processing is done yet.
       
   337    * @param urlString valid URL string for XSL stylesheet.
       
   338    */
       
   339   public void setStyleURL(String urlString)
       
   340   {
       
   341     m_styleURL = urlString;
       
   342   }
       
   343 
       
   344   /**
       
   345    * Set the URL to the XML document that will be transformed
       
   346    * with the XSL stylesheet.  No processing is done yet.
       
   347    * @param urlString valid URL string for XML document.
       
   348    */
       
   349   public void setDocumentURL(String urlString)
       
   350   {
       
   351     m_documentURL = urlString;
       
   352   }
       
   353 
       
   354   /**
       
   355    * The processor keeps a cache of the source and
       
   356    * style trees, so call this method if they have changed
       
   357    * or you want to do garbage collection.
       
   358    */
       
   359   public void freeCache()
       
   360   {
       
   361     m_styleURLOfCached = null;
       
   362     m_documentURLOfCached = null;
       
   363   }
       
   364 
       
   365   /**
       
   366    * Set an attribute in the stylesheet, which gives the ability
       
   367    * to have some dynamic selection control.
       
   368    * @param nameOfIDAttrOfElemToModify The name of an attribute to search for a unique id.
       
   369    * @param elemId The unique ID to look for.
       
   370    * @param attrName Once the element is found, the name of the attribute to set.
       
   371    * @param value The value to set the attribute to.
       
   372    */
       
   373   public void setStyleSheetAttribute(String nameOfIDAttrOfElemToModify,
       
   374                                      String elemId, String attrName,
       
   375                                      String value)
       
   376   {
       
   377     m_nameOfIDAttrOfElemToModify = nameOfIDAttrOfElemToModify;
       
   378     m_elemIdToModify = elemId;
       
   379     m_attrNameToSet = attrName;
       
   380     m_attrValueToSet = value;
       
   381   }
       
   382 
       
   383 
       
   384   /**
       
   385    * Stylesheet parameter key/value pair stored in a hashtable
       
   386    */
       
   387   transient Hashtable m_parameters;
       
   388 
       
   389   /**
       
   390    * Submit a stylesheet parameter.
       
   391    *
       
   392    * @param key stylesheet parameter key
       
   393    * @param expr the parameter expression to be submitted.
       
   394    * @see javax.xml.transform.Transformer#setParameter(String,Object)
       
   395    */
       
   396   public void setStylesheetParam(String key, String expr)
       
   397   {
       
   398     m_parameters.put(key, expr);
       
   399   }
       
   400 
       
   401   /**
       
   402    * Given a String containing markup, escape the markup so it
       
   403    * can be displayed in the browser.
       
   404    *
       
   405    * @param s String to escape
       
   406    *
       
   407    * The escaped string.
       
   408    */
       
   409   public String escapeString(String s)
       
   410   {
       
   411     StringBuffer sb = new StringBuffer();
       
   412     int length = s.length();
       
   413 
       
   414     for (int i = 0; i < length; i++)
       
   415     {
       
   416       char ch = s.charAt(i);
       
   417 
       
   418       if ('<' == ch)
       
   419       {
       
   420         sb.append("&lt;");
       
   421       }
       
   422       else if ('>' == ch)
       
   423       {
       
   424         sb.append("&gt;");
       
   425       }
       
   426       else if ('&' == ch)
       
   427       {
       
   428         sb.append("&amp;");
       
   429       }
       
   430       else if (0xd800 <= ch && ch < 0xdc00)
       
   431       {
       
   432         // UTF-16 surrogate
       
   433         int next;
       
   434 
       
   435         if (i + 1 >= length)
       
   436         {
       
   437           throw new RuntimeException(
       
   438             XSLMessages.createMessage(
       
   439               XSLTErrorResources.ER_INVALID_UTF16_SURROGATE,
       
   440               new Object[]{ Integer.toHexString(ch) }));  //"Invalid UTF-16 surrogate detected: "
       
   441 
       
   442           //+Integer.toHexString(ch)+ " ?");
       
   443         }
       
   444         else
       
   445         {
       
   446           next = s.charAt(++i);
       
   447 
       
   448           if (!(0xdc00 <= next && next < 0xe000))
       
   449             throw new RuntimeException(
       
   450               XSLMessages.createMessage(
       
   451                 XSLTErrorResources.ER_INVALID_UTF16_SURROGATE,
       
   452                 new Object[]{
       
   453                   Integer.toHexString(ch) + " "
       
   454                   + Integer.toHexString(next) }));  //"Invalid UTF-16 surrogate detected: "
       
   455 
       
   456           //+Integer.toHexString(ch)+" "+Integer.toHexString(next));
       
   457           next = ((ch - 0xd800) << 10) + next - 0xdc00 + 0x00010000;
       
   458         }
       
   459         sb.append("&#x");
       
   460         sb.append(Integer.toHexString(next));
       
   461         sb.append(";");
       
   462       }
       
   463       else
       
   464       {
       
   465         sb.append(ch);
       
   466       }
       
   467     }
       
   468     return sb.toString();
       
   469   }
       
   470 
       
   471   /**
       
   472    * Assuming the stylesheet URL and the input XML URL have been set,
       
   473    * perform the transformation and return the result as a String.
       
   474    *
       
   475    * @return A string that contains the contents pointed to by the URL.
       
   476    *
       
   477    */
       
   478   public String getHtmlText()
       
   479   {
       
   480     m_trustedAgent.m_getData = true;
       
   481     m_callThread = Thread.currentThread();
       
   482     try
       
   483     {
       
   484       synchronized (m_callThread)
       
   485       {
       
   486         m_callThread.wait();
       
   487       }
       
   488     }
       
   489     catch (InterruptedException ie)
       
   490     {
       
   491       System.out.println(ie.getMessage());
       
   492     }
       
   493     return m_htmlText;
       
   494   }
       
   495 
       
   496   /**
       
   497    * Get an XML document (or stylesheet)
       
   498    *
       
   499    * @param treeURL valid URL string for the document.
       
   500    *
       
   501    * @return document
       
   502    *
       
   503    * @throws IOException
       
   504    */
       
   505   public String getTreeAsText(String treeURL) throws IOException
       
   506   {
       
   507     m_treeURL = treeURL;
       
   508     m_trustedAgent.m_getData = true;
       
   509     m_trustedAgent.m_getSource = true;
       
   510     m_callThread = Thread.currentThread();
       
   511     try
       
   512     {
       
   513       synchronized (m_callThread)
       
   514       {
       
   515         m_callThread.wait();
       
   516       }
       
   517     }
       
   518     catch (InterruptedException ie)
       
   519     {
       
   520       System.out.println(ie.getMessage());
       
   521     }
       
   522     return m_sourceText;
       
   523   }
       
   524 
       
   525   /**
       
   526    * Use a Transformer to copy the source document
       
   527    * to a StreamResult.
       
   528    *
       
   529    * @return the document as a string
       
   530    */
       
   531   private String getSource() throws TransformerException
       
   532   {
       
   533     StringWriter osw = new StringWriter();
       
   534     PrintWriter pw = new PrintWriter(osw, false);
       
   535     String text = "";
       
   536     try
       
   537     {
       
   538       URL docURL = new URL(m_documentBase, m_treeURL);
       
   539       synchronized (m_tfactory)
       
   540       {
       
   541         Transformer transformer = m_tfactory.newTransformer();
       
   542         StreamSource source = new StreamSource(docURL.toString());
       
   543         StreamResult result = new StreamResult(pw);
       
   544         transformer.transform(source, result);
       
   545         text = osw.toString();
       
   546       }
       
   547     }
       
   548     catch (MalformedURLException e)
       
   549     {
       
   550       e.printStackTrace();
       
   551       throw new RuntimeException(e.getMessage());
       
   552     }
       
   553     catch (Exception any_error)
       
   554     {
       
   555       any_error.printStackTrace();
       
   556     }
       
   557     return text;
       
   558   }
       
   559 
       
   560   /**
       
   561    * Get the XML source Tree as a text string suitable
       
   562    * for display in a browser.  Note that this is for display of the
       
   563    * XML itself, not for rendering of HTML by the browser.
       
   564    *
       
   565    * @return XML source document as a string.
       
   566    * @throws Exception thrown if tree can not be converted.
       
   567    */
       
   568   public String getSourceTreeAsText() throws Exception
       
   569   {
       
   570     return getTreeAsText(m_documentURL);
       
   571   }
       
   572 
       
   573   /**
       
   574    * Get the XSL style Tree as a text string suitable
       
   575    * for display in a browser.  Note that this is for display of the
       
   576    * XML itself, not for rendering of HTML by the browser.
       
   577    *
       
   578    * @return The XSL stylesheet as a string.
       
   579    * @throws Exception thrown if tree can not be converted.
       
   580    */
       
   581   public String getStyleTreeAsText() throws Exception
       
   582   {
       
   583     return getTreeAsText(m_styleURL);
       
   584   }
       
   585 
       
   586   /**
       
   587    * Get the HTML result Tree as a text string suitable
       
   588    * for display in a browser.  Note that this is for display of the
       
   589    * XML itself, not for rendering of HTML by the browser.
       
   590    *
       
   591    * @return Transformation result as unmarked text.
       
   592    * @throws Exception thrown if tree can not be converted.
       
   593    */
       
   594   public String getResultTreeAsText() throws Exception
       
   595   {
       
   596     return escapeString(getHtmlText());
       
   597   }
       
   598 
       
   599   /**
       
   600    * Process a document and a stylesheet and return
       
   601    * the transformation result.  If one of these is null, the
       
   602    * existing value (of a previous transformation) is not affected.
       
   603    *
       
   604    * @param doc URL string to XML document
       
   605    * @param style URL string to XSL stylesheet
       
   606    *
       
   607    * @return HTML transformation result
       
   608    */
       
   609   public String transformToHtml(String doc, String style)
       
   610   {
       
   611 
       
   612     if (null != doc)
       
   613     {
       
   614       m_documentURL = doc;
       
   615     }
       
   616 
       
   617     if (null != style)
       
   618     {
       
   619       m_styleURL = style;
       
   620     }
       
   621 
       
   622     return getHtmlText();
       
   623   }
       
   624 
       
   625   /**
       
   626    * Process a document and a stylesheet and return
       
   627    * the transformation result. Use the xsl:stylesheet PI to find the
       
   628    * document, if one exists.
       
   629    *
       
   630    * @param doc  URL string to XML document containing an xsl:stylesheet PI.
       
   631    *
       
   632    * @return HTML transformation result
       
   633    */
       
   634   public String transformToHtml(String doc)
       
   635   {
       
   636 
       
   637     if (null != doc)
       
   638     {
       
   639       m_documentURL = doc;
       
   640     }
       
   641 
       
   642     m_styleURL = null;
       
   643 
       
   644     return getHtmlText();
       
   645   }
       
   646 
       
   647 
       
   648   /**
       
   649    * Process the transformation.
       
   650    *
       
   651    * @return The transformation result as a string.
       
   652    *
       
   653    * @throws TransformerException
       
   654    */
       
   655   private String processTransformation() throws TransformerException
       
   656   {
       
   657     String htmlData = null;
       
   658     this.showStatus("Waiting for Transformer and Parser to finish loading and JITing...");
       
   659 
       
   660     synchronized (m_tfactory)
       
   661     {
       
   662      URL documentURL = null;
       
   663       URL styleURL = null;
       
   664       StringWriter osw = new StringWriter();
       
   665       PrintWriter pw = new PrintWriter(osw, false);
       
   666       StreamResult result = new StreamResult(pw);
       
   667 
       
   668       this.showStatus("Begin Transformation...");
       
   669       try
       
   670       {
       
   671         documentURL = new URL(m_codeBase, m_documentURL);
       
   672         StreamSource xmlSource = new StreamSource(documentURL.toString());
       
   673 
       
   674         styleURL = new URL(m_codeBase, m_styleURL);
       
   675         StreamSource xslSource = new StreamSource(styleURL.toString());
       
   676 
       
   677         Transformer transformer = m_tfactory.newTransformer(xslSource);
       
   678 
       
   679 
       
   680         Enumeration m_keys = m_parameters.keys();
       
   681         while (m_keys.hasMoreElements()){
       
   682           Object key = m_keys.nextElement();
       
   683           Object expression = m_parameters.get(key);
       
   684           transformer.setParameter((String) key, expression);
       
   685         }
       
   686         transformer.transform(xmlSource, result);
       
   687       }
       
   688       catch (TransformerConfigurationException tfe)
       
   689       {
       
   690         tfe.printStackTrace();
       
   691         throw new RuntimeException(tfe.getMessage());
       
   692       }
       
   693       catch (MalformedURLException e)
       
   694       {
       
   695         e.printStackTrace();
       
   696         throw new RuntimeException(e.getMessage());
       
   697       }
       
   698 
       
   699       this.showStatus("Transformation Done!");
       
   700       htmlData = osw.toString();
       
   701     }
       
   702     return htmlData;
       
   703   }
       
   704 
       
   705   /**
       
   706    * This class maintains a worker thread that that is
       
   707    * trusted and can do things like access data.  You need
       
   708    * this because the thread that is called by the browser
       
   709    * is not trusted and can't access data from the URLs.
       
   710    */
       
   711   class TrustedAgent implements Runnable
       
   712   {
       
   713 
       
   714     /**
       
   715      * Specifies whether the worker thread should perform a transformation.
       
   716      */
       
   717     public boolean m_getData = false;
       
   718 
       
   719     /**
       
   720      * Specifies whether the worker thread should get an XML document or XSL stylesheet.
       
   721      */
       
   722     public boolean m_getSource = false;
       
   723 
       
   724     /**
       
   725      * The real work is done from here.
       
   726      *
       
   727      */
       
   728     public void run()
       
   729     {
       
   730       while (true)
       
   731       {
       
   732         m_trustedWorker.yield();
       
   733 
       
   734         if (m_getData)  // Perform a transformation or get a document.
       
   735         {
       
   736           try
       
   737           {
       
   738             m_getData = false;
       
   739             m_htmlText = null;
       
   740             m_sourceText = null;
       
   741             if (m_getSource)  // Get a document.
       
   742             {
       
   743               m_getSource = false;
       
   744               m_sourceText = getSource();
       
   745             }
       
   746             else              // Perform a transformation.
       
   747               m_htmlText = processTransformation();
       
   748           }
       
   749           catch (Exception e)
       
   750           {
       
   751             e.printStackTrace();
       
   752           }
       
   753           finally
       
   754           {
       
   755             synchronized (m_callThread)
       
   756             {
       
   757               m_callThread.notify();
       
   758             }
       
   759           }
       
   760         }
       
   761         else
       
   762         {
       
   763           try
       
   764           {
       
   765             m_trustedWorker.sleep(50);
       
   766           }
       
   767           catch (InterruptedException ie)
       
   768           {
       
   769             ie.printStackTrace();
       
   770           }
       
   771         }
       
   772       }
       
   773     }
       
   774   }
       
   775 
       
   776   // For compatiblity with old serialized objects
       
   777   // We will change non-serialized fields and change methods
       
   778   // and not have this break us.
       
   779   private static final long serialVersionUID=4618876841979251422L;
       
   780 
       
   781   // For compatibility when de-serializing old objects
       
   782   private void readObject(java.io.ObjectInputStream inStream) throws IOException, ClassNotFoundException
       
   783   {
       
   784       inStream.defaultReadObject();
       
   785 
       
   786       // Needed assignment of non-serialized fields
       
   787 
       
   788       // A TransformerFactory is not guaranteed to be serializable,
       
   789       // so we create one here
       
   790       m_tfactory = TransformerFactory.newInstance();
       
   791   }
       
   792 }