code: /*
   * 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$
   */
  
  import java.applet.Applet;
  
  import java.awt.BorderLayout;
  import java.awt.Button;
  import java.awt.Frame;
  import java.awt.Label;
  import java.awt.Panel;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  
  import java.io.PrintWriter;
  import java.io.StringWriter;
  
  import javax.xml.transform.Transformer;
  import javax.xml.transform.TransformerFactory;
  import javax.xml.transform.TransformerException;
  import javax.xml.transform.ErrorListener;
  import javax.xml.transform.stream.StreamResult;
  import javax.xml.transform.stream.StreamSource;
  
  /**
   * This applet demonstrates how XSL transformations can be made to run in
   * browsers without native XSLT support.
   *
   * Note that the XSLTC transformation engine is invoked through the JAXP
   * interface, using the XSLTC "use-classpath" attribute.  The
   * "use-classpath" attribute specifies to the XSLTC TransformerFactory
   * that a precompiled version of the stylesheet (translet) may be available,
   * and that that should be used in preference to recompiling the stylesheet.
   * @author Morten Jorgensen
   * @author Jacek Ambroziak
   */
  public final class TransformApplet extends Applet {
      TransformerFactory tf;
      TransformDelegate transformThread;
      /**
       * This class implements a dialog box used for XSL messages/comments
       */
      public class MessageFrame extends Frame {
  
          public Frame frame;
  
          public class ButtonHandler implements ActionListener {
              public void actionPerformed(ActionEvent e) {
                  frame.setVisible(false);
              }
          }
  
          /**
           * This method handles xml:message and xsl:comment by displaying
           * the message/comment in a dialog box.
           */
          public MessageFrame(String title, String message) {
              super(title);
              frame = this; // Make visible to ButtonHandler
              setSize(320,200);
  
              // Create a panel for the message itself
              Panel center = new Panel();
              center.add(new Label(message));
  
              // Create a panel for the 'OK' button
              Panel bottom = new Panel();
              Button okButton = new Button("   OK   ");
              okButton.addActionListener(new ButtonHandler());
              bottom.add(okButton);
  
              // Add the two panels to the window/frame
              add(center, BorderLayout.CENTER);
              add(bottom,BorderLayout.SOUTH);
  
              // Show the whole thing
              setVisible(true);
          }
  
      }
  
      /**
       * The applet uses this method to display messages and comments
       * generated by xsl:message and xsl:comment elements.
       */
      public class AppletErrorListener implements ErrorListener {
          public void displayMessage(TransformerException e) {
              MessageFrame z = new MessageFrame("XSL transformation alert",
                                                e.getMessageAndLocation());
          }
  
          public void error(TransformerException e) {
              displayMessage(e);
          }
  
          public void fatalError(TransformerException e) {
              displayMessage(e);
          }
  
          public void warning(TransformerException e) {
                      displayMessage(e);
          }
      }
  
      /**
       * This method is the main body of the applet. The method is called
       * by some JavaScript code in an HTML document.
       */
      public synchronized String transform(Object arg1, Object arg2) {
          final String stylesheetURL = (String)arg1;
          final String documentURL = (String)arg2;
  
          transformThread.setStylesheetURL(stylesheetURL);
          transformThread.setDocumentURL(documentURL);
          transformThread.setWaiting(false);
          transformThread.wakeUp();
          try{
              wait();
          } catch (InterruptedException e){}
          return transformThread.getOutput();
      }
  
      public void start() {
          transform(getParameter("stylesheet-name"),
                    getParameter("input-document"));
      }
      public void destroy() {
          transformThread.destroy();
      }
      public void init() {
          tf = TransformerFactory.newInstance();
          try {
              tf.setAttribute("use-classpath", Boolean.TRUE);
          } catch (IllegalArgumentException iae) {
              System.err.println("Could not set XSLTC-specific TransformerFactory"
                                 + " attributes.  Transformation failed.");
          }
          // Another thread is created to keep the context class loader
          // information.  When use JDK 1.4 plugin for browser, to get around the
          // problem with the bundled old version of xalan and endorsed class
          // loading mechanism
          transformThread = new TransformDelegate(true);
          Thread t = new Thread(transformThread);
          t.setName("transformThread");
          t.start();
      }
      public String getOutput(){
          return transformThread.getOutput();
      }
      public synchronized void wakeUp() {
          notifyAll();
      }
      class TransformDelegate implements Runnable {
          private boolean isRunning, isWaiting;
          private String stylesheetURL, documentURL;
          private String outPut;
          public TransformDelegate(boolean arg) {
              isRunning = arg;
              isWaiting = true;
          }
          public synchronized void run() {
              while(isRunning){
                  while(isWaiting){
                      try {
                          wait();
                      } catch (InterruptedException e){}
                  }
                  transform();
                  isWaiting = true;
                  TransformApplet.this.wakeUp();
              }
          }
  
          public void setStylesheetURL(String arg){
              stylesheetURL = arg;
          }
          public void setDocumentURL(String arg) {
              documentURL = arg;
          }
          public String getStylesheetURL(){
              return stylesheetURL;
          }
          public String getDocumentURL() {
              return documentURL;
          }
          public void setWaiting(boolean arg) {
              isWaiting = arg;
          }
          public void destroy() {
              isRunning = false;
          }
          public synchronized void wakeUp() {
              notifyAll();
          }
          public String getOutput(){
              return outPut;
          }
  
          public void transform(){
              String xslURL = getStylesheetURL();
              String docURL = getDocumentURL();
              // Initialise the output stream
              StringWriter sout = new StringWriter();
              PrintWriter out = new PrintWriter(sout);
              // Check that the parameters are valid
              try {
                  if (xslURL == null || docURL == null) {
                      out.println("<h1>Transformation error</h1>");
                      out.println("The parameters <b><tt>stylesheetURL</tt></b> "+
                                  "and <b><tt>source</tt></b> must be specified");
                  } else {
                      Transformer t = tf.newTransformer(new StreamSource(xslURL));
                      t.setErrorListener(new AppletErrorListener());
  
                      final long start = System.currentTimeMillis();
  
                      t.transform(new StreamSource(docURL),
                                  new StreamResult(out));
  
                      final long done = System.currentTimeMillis() - start;
                      out.println("<!-- transformed by XSLTC in " + done
                                  + "msecs -->");
                  }
                  // Now close up the sink, and return the HTML output in the
                  // StringWrite object as a string.
                  out.close();
                  System.err.println("Transformation complete!");
                  System.err.println(sout.toString());
                  outPut = sout.toString();
                  sout.close();
              } catch (RuntimeException e) {
                  out.println("<h1>RTE</h1>");
                  out.close();
                  outPut = sout.toString();
              } catch (Exception e) {
                  out.println("<h1>exception</h1>");
                  out.println(e.toString());
                  out.close();
                  outPut = sout.toString();
              }
          }
      }
  }
  