1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the  "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 /*
19  * $Id: TransformApplet.java 478660 2006-11-23 20:43:59Z minchau $
20  */
21 
22 import java.applet.Applet;
23 
24 import java.awt.BorderLayout;
25 import java.awt.Button;
26 import java.awt.Frame;
27 import java.awt.Label;
28 import java.awt.Panel;
29 import java.awt.event.ActionEvent;
30 import java.awt.event.ActionListener;
31 
32 import java.io.PrintWriter;
33 import java.io.StringWriter;
34 
35 import javax.xml.transform.Transformer;
36 import javax.xml.transform.TransformerFactory;
37 import javax.xml.transform.TransformerException;
38 import javax.xml.transform.ErrorListener;
39 import javax.xml.transform.stream.StreamResult;
40 import javax.xml.transform.stream.StreamSource;
41 
42 /**
43  * This applet demonstrates how XSL transformations can be made to run in
44  * browsers without native XSLT support.
45  *
46  * Note that the XSLTC transformation engine is invoked through the JAXP
47  * interface, using the XSLTC "use-classpath" attribute.  The
48  * "use-classpath" attribute specifies to the XSLTC TransformerFactory
49  * that a precompiled version of the stylesheet (translet) may be available,
50  * and that that should be used in preference to recompiling the stylesheet.
51  * @author Morten Jorgensen
52  * @author Jacek Ambroziak
53  */
54 public final class TransformApplet extends Applet {
55     TransformerFactory tf;
56     TransformDelegate transformThread;
57     /**
58      * This class implements a dialog box used for XSL messages/comments
59      */
60     public class MessageFrame extends Frame {
61 
62         public Frame frame;
63 
64         public class ButtonHandler implements ActionListener {
actionPerformed(ActionEvent e)65             public void actionPerformed(ActionEvent e) {
66                 frame.setVisible(false);
67             }
68         }
69 
70         /**
71          * This method handles xml:message and xsl:comment by displaying
72          * the message/comment in a dialog box.
73          */
MessageFrame(String title, String message)74         public MessageFrame(String title, String message) {
75             super(title);
76             frame = this; // Make visible to ButtonHandler
77             setSize(320,200);
78 
79             // Create a panel for the message itself
80             Panel center = new Panel();
81             center.add(new Label(message));
82 
83             // Create a panel for the 'OK' button
84             Panel bottom = new Panel();
85             Button okButton = new Button("   OK   ");
86             okButton.addActionListener(new ButtonHandler());
87             bottom.add(okButton);
88 
89             // Add the two panels to the window/frame
90             add(center, BorderLayout.CENTER);
91             add(bottom,BorderLayout.SOUTH);
92 
93             // Show the whole thing
94             setVisible(true);
95         }
96 
97     }
98 
99     /**
100      * The applet uses this method to display messages and comments
101      * generated by xsl:message and xsl:comment elements.
102      */
103     public class AppletErrorListener implements ErrorListener {
displayMessage(TransformerException e)104         public void displayMessage(TransformerException e) {
105             MessageFrame z = new MessageFrame("XSL transformation alert",
106                                               e.getMessageAndLocation());
107         }
108 
error(TransformerException e)109         public void error(TransformerException e) {
110             displayMessage(e);
111         }
112 
fatalError(TransformerException e)113         public void fatalError(TransformerException e) {
114             displayMessage(e);
115         }
116 
warning(TransformerException e)117         public void warning(TransformerException e) {
118                     displayMessage(e);
119         }
120     }
121 
122     /**
123      * This method is the main body of the applet. The method is called
124      * by some JavaScript code in an HTML document.
125      */
transform(Object arg1, Object arg2)126     public synchronized String transform(Object arg1, Object arg2) {
127         final String stylesheetURL = (String)arg1;
128         final String documentURL = (String)arg2;
129 
130         transformThread.setStylesheetURL(stylesheetURL);
131         transformThread.setDocumentURL(documentURL);
132         transformThread.setWaiting(false);
133         transformThread.wakeUp();
134         try{
135             wait();
136         } catch (InterruptedException e){}
137         return transformThread.getOutput();
138     }
139 
start()140     public void start() {
141         transform(getParameter("stylesheet-name"),
142                   getParameter("input-document"));
143     }
destroy()144     public void destroy() {
145         transformThread.destroy();
146     }
init()147     public void init() {
148         tf = TransformerFactory.newInstance();
149         try {
150             tf.setAttribute("use-classpath", Boolean.TRUE);
151         } catch (IllegalArgumentException iae) {
152             System.err.println("Could not set XSLTC-specific TransformerFactory"
153                                + " attributes.  Transformation failed.");
154         }
155         // Another thread is created to keep the context class loader
156         // information.  When use JDK 1.4 plugin for browser, to get around the
157         // problem with the bundled old version of xalan and endorsed class
158         // loading mechanism
159         transformThread = new TransformDelegate(true);
160         Thread t = new Thread(transformThread);
161         t.setName("transformThread");
162         t.start();
163     }
getOutput()164     public String getOutput(){
165         return transformThread.getOutput();
166     }
wakeUp()167     public synchronized void wakeUp() {
168         notifyAll();
169     }
170     class TransformDelegate implements Runnable {
171         private boolean isRunning, isWaiting;
172         private String stylesheetURL, documentURL;
173         private String outPut;
TransformDelegate(boolean arg)174         public TransformDelegate(boolean arg) {
175             isRunning = arg;
176             isWaiting = true;
177         }
run()178         public synchronized void run() {
179             while(isRunning){
180                 while(isWaiting){
181                     try {
182                         wait();
183                     } catch (InterruptedException e){}
184                 }
185                 transform();
186                 isWaiting = true;
187                 TransformApplet.this.wakeUp();
188             }
189         }
190 
setStylesheetURL(String arg)191         public void setStylesheetURL(String arg){
192             stylesheetURL = arg;
193         }
setDocumentURL(String arg)194         public void setDocumentURL(String arg) {
195             documentURL = arg;
196         }
getStylesheetURL()197         public String getStylesheetURL(){
198             return stylesheetURL;
199         }
getDocumentURL()200         public String getDocumentURL() {
201             return documentURL;
202         }
setWaiting(boolean arg)203         public void setWaiting(boolean arg) {
204             isWaiting = arg;
205         }
destroy()206         public void destroy() {
207             isRunning = false;
208         }
wakeUp()209         public synchronized void wakeUp() {
210             notifyAll();
211         }
getOutput()212         public String getOutput(){
213             return outPut;
214         }
215 
transform()216         public void transform(){
217             String xslURL = getStylesheetURL();
218             String docURL = getDocumentURL();
219             // Initialise the output stream
220             StringWriter sout = new StringWriter();
221             PrintWriter out = new PrintWriter(sout);
222             // Check that the parameters are valid
223             try {
224                 if (xslURL == null || docURL == null) {
225                     out.println("<h1>Transformation error</h1>");
226                     out.println("The parameters <b><tt>stylesheetURL</tt></b> "+
227                                 "and <b><tt>source</tt></b> must be specified");
228                 } else {
229                     Transformer t = tf.newTransformer(new StreamSource(xslURL));
230                     t.setErrorListener(new AppletErrorListener());
231 
232                     final long start = System.currentTimeMillis();
233 
234                     t.transform(new StreamSource(docURL),
235                                 new StreamResult(out));
236 
237                     final long done = System.currentTimeMillis() - start;
238                     out.println("<!-- transformed by XSLTC in " + done
239                                 + "msecs -->");
240                 }
241                 // Now close up the sink, and return the HTML output in the
242                 // StringWrite object as a string.
243                 out.close();
244                 System.err.println("Transformation complete!");
245                 System.err.println(sout.toString());
246                 outPut = sout.toString();
247                 sout.close();
248             } catch (RuntimeException e) {
249                 out.println("<h1>RTE</h1>");
250                 out.close();
251                 outPut = sout.toString();
252             } catch (Exception e) {
253                 out.println("<h1>exception</h1>");
254                 out.println(e.toString());
255                 out.close();
256                 outPut = sout.toString();
257             }
258         }
259     }
260 }
261