KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > bridge > ScriptingEnvironment


1 /*
2
3    Copyright 2002-2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.bridge;
19
20 import java.io.BufferedReader JavaDoc;
21 import java.io.InputStream JavaDoc;
22 import java.io.InputStreamReader JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.OutputStream JavaDoc;
25 import java.io.OutputStreamWriter JavaDoc;
26 import java.io.Reader JavaDoc;
27 import java.io.StringReader JavaDoc;
28 import java.io.UnsupportedEncodingException JavaDoc;
29 import java.io.Writer JavaDoc;
30
31 import java.net.URL JavaDoc;
32 import java.net.URLConnection JavaDoc;
33
34 import java.util.HashMap JavaDoc;
35 import java.util.Map JavaDoc;
36 import java.util.Timer JavaDoc;
37 import java.util.TimerTask JavaDoc;
38 import java.util.zip.GZIPOutputStream JavaDoc;
39 import java.util.zip.DeflaterOutputStream JavaDoc;
40
41 import org.apache.batik.dom.GenericDOMImplementation;
42 import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
43 import org.apache.batik.dom.svg.SVGOMDocument;
44 import org.apache.batik.dom.util.SAXDocumentFactory;
45 import org.apache.batik.dom.util.XLinkSupport;
46 import org.apache.batik.script.Interpreter;
47 import org.apache.batik.script.InterpreterException;
48 import org.apache.batik.util.EncodingUtilities;
49 import org.apache.batik.util.ParsedURL;
50 import org.apache.batik.util.RunnableQueue;
51 import org.apache.batik.util.SVGConstants;
52 import org.apache.batik.util.XMLResourceDescriptor;
53
54 import org.w3c.dom.Document JavaDoc;
55 import org.w3c.dom.Element JavaDoc;
56 import org.w3c.dom.Node JavaDoc;
57 import org.w3c.dom.events.Event JavaDoc;
58 import org.w3c.dom.events.EventListener JavaDoc;
59 import org.w3c.dom.events.EventTarget JavaDoc;
60 import org.w3c.dom.events.MutationEvent JavaDoc;
61 import org.w3c.dom.svg.SVGDocument;
62
63 /**
64  * This class contains the informations needed by the SVG scripting.
65  *
66  * @author <a HREF="mailto:stephane@hillion.org">Stephane Hillion</a>
67  * @version $Id: ScriptingEnvironment.java,v 1.49 2005/04/02 14:26:09 deweese Exp $
68  */

69 public class ScriptingEnvironment extends BaseScriptingEnvironment {
70
71     /**
72      * Used in 'parseXML()'.
73      */

74     protected final static String JavaDoc FRAGMENT_PREFIX =
75         "<svg xmlns='" +
76         SVGConstants.SVG_NAMESPACE_URI +
77         "' xmlns:xlink='" +
78         XLinkSupport.XLINK_NAMESPACE_URI +
79         "'>";
80
81     protected final static String JavaDoc FRAGMENT_SUFFIX =
82         "</svg>";
83
84     public final static String JavaDoc [] SVG_EVENT_ATTRS = {
85         "onabort", // SVG element
86
"onerror", // SVG element
87
"onresize", // SVG element
88
"onscroll", // SVG element
89
"onunload", // SVG element
90
"onzoom", // SVG element
91

92         "onbegin", // SMIL
93
"onend", // SMIL
94
"onrepeat", // SMIL
95

96         "onfocusin", // UI Events
97
"onfocusout", // UI Events
98
"onactivate", // UI Events
99
"onclick", // UI Events
100

101         "onmousedown", // UI Events
102
"onmouseup", // UI Events
103
"onmouseover", // UI Events
104
"onmouseout", // UI Events
105
"onmousemove", // UI Events
106

107         "onkeypress", // UI Events
108
"onkeydown", // UI Events
109
"onkeyup" // UI Events
110
};
111
112     public final static String JavaDoc [] SVG_DOM_EVENT = {
113         "SVGAbort", // SVG element
114
"SVGError", // SVG element
115
"SVGResize", // SVG element
116
"SVGScroll", // SVG element
117
"SVGUnload", // SVG element
118
"SVGZoom", // SVG element
119

120         "beginEvent", // SMIL
121
"endEvent", // SMIL
122
"repeatEvent", // SMIL
123

124         "DOMFocusIn", // UI Events
125
"DOMFocusOut", // UI Events
126
"DOMActivate", // UI Events
127
"click", // UI Events
128
"mousedown", // UI Events
129
"mouseup", // UI Events
130
"mouseover", // UI Events
131
"mouseout", // UI Events
132
"mousemove", // UI Events
133
"keypress", // UI Events
134
"keydown", // UI Events
135
"keyup" // UI Events
136
};
137
138     /**
139      * The timer for periodic or delayed tasks.
140      */

141     protected Timer JavaDoc timer = new Timer JavaDoc(true);
142
143     /**
144      * The update manager.
145      */

146     protected UpdateManager updateManager;
147
148     /**
149      * The update runnable queue.
150      */

151     protected RunnableQueue updateRunnableQueue;
152
153     /**
154      * The DOMNodeInserted event listener.
155      */

156     protected EventListener JavaDoc domNodeInsertedListener
157         = new DOMNodeInsertedListener();
158
159     /**
160      * The DOMNodeRemoved event listener.
161      */

162     protected EventListener JavaDoc domNodeRemovedListener
163         = new DOMNodeRemovedListener();
164
165     /**
166      * The DOMAttrModified event listener.
167      */

168     protected EventListener JavaDoc domAttrModifiedListener
169         = new DOMAttrModifiedListener();
170
171     /**
172      * The SVGAbort event listener.
173      */

174     protected EventListener JavaDoc svgAbortListener =
175         new ScriptingEventListener("onabort");
176
177     /**
178      * The SVGError event listener.
179      */

180     protected EventListener JavaDoc svgErrorListener =
181         new ScriptingEventListener("onerror");
182
183     /**
184      * The SVGResize event listener.
185      */

186     protected EventListener JavaDoc svgResizeListener =
187         new ScriptingEventListener("onresize");
188
189     /**
190      * The SVGScroll event listener.
191      */

192     protected EventListener JavaDoc svgScrollListener =
193         new ScriptingEventListener("onscroll");
194
195     /**
196      * The SVGUnload event listener.
197      */

198     protected EventListener JavaDoc svgUnloadListener =
199         new ScriptingEventListener("onunload");
200
201     /**
202      * The SVGZoom event listener.
203      */

204     protected EventListener JavaDoc svgZoomListener =
205         new ScriptingEventListener("onzoom");
206
207     /**
208      * The begin event listener.
209      */

210     protected EventListener JavaDoc beginListener =
211         new ScriptingEventListener("onbegin");
212
213     /**
214      * The end event listener.
215      */

216     protected EventListener JavaDoc endListener =
217         new ScriptingEventListener("onend");
218
219     /**
220      * The repeat event listener.
221      */

222     protected EventListener JavaDoc repeatListener =
223         new ScriptingEventListener("onrepeat");
224
225     /**
226      * The focusin event listener.
227      */

228     protected EventListener JavaDoc focusinListener =
229         new ScriptingEventListener("onfocusin");
230
231     /**
232      * The focusout event listener.
233      */

234     protected EventListener JavaDoc focusoutListener =
235         new ScriptingEventListener("onfocusout");
236
237     /**
238      * The activate event listener.
239      */

240     protected EventListener JavaDoc activateListener =
241         new ScriptingEventListener("onactivate");
242
243     /**
244      * The click event listener.
245      */

246     protected EventListener JavaDoc clickListener =
247         new ScriptingEventListener("onclick");
248
249     /**
250      * The mousedown event listener.
251      */

252     protected EventListener JavaDoc mousedownListener =
253         new ScriptingEventListener("onmousedown");
254
255     /**
256      * The mouseup event listener.
257      */

258     protected EventListener JavaDoc mouseupListener =
259         new ScriptingEventListener("onmouseup");
260
261     /**
262      * The mouseover event listener.
263      */

264     protected EventListener JavaDoc mouseoverListener =
265         new ScriptingEventListener("onmouseover");
266
267     /**
268      * The mouseout event listener.
269      */

270     protected EventListener JavaDoc mouseoutListener =
271         new ScriptingEventListener("onmouseout");
272
273     /**
274      * The mousemove event listener.
275      */

276     protected EventListener JavaDoc mousemoveListener =
277         new ScriptingEventListener("onmousemove");
278
279     /**
280      * The keypress event listener.
281      */

282     protected EventListener JavaDoc keypressListener =
283         new ScriptingEventListener("onkeypress");
284
285     /**
286      * The keydown event listener.
287      */

288     protected EventListener JavaDoc keydownListener =
289         new ScriptingEventListener("onkeydown");
290
291     /**
292      * The keyup event listener.
293      */

294     protected EventListener JavaDoc keyupListener =
295         new ScriptingEventListener("onkeyup");
296
297     
298     protected EventListener JavaDoc [] listeners = {
299         svgAbortListener,
300         svgErrorListener,
301         svgResizeListener,
302         svgScrollListener,
303         svgUnloadListener,
304         svgZoomListener,
305
306         beginListener,
307         endListener,
308         repeatListener,
309
310         focusinListener,
311         focusoutListener,
312         activateListener,
313         clickListener,
314
315         mousedownListener,
316         mouseupListener,
317         mouseoverListener,
318         mouseoutListener,
319         mousemoveListener,
320
321         keypressListener,
322         keydownListener,
323         keyupListener
324     };
325
326     Map JavaDoc attrToDOMEvent = new HashMap JavaDoc(SVG_EVENT_ATTRS.length);
327     Map JavaDoc attrToListener = new HashMap JavaDoc(SVG_EVENT_ATTRS.length);
328     {
329         for (int i=0; i<SVG_EVENT_ATTRS.length; i++) {
330             attrToDOMEvent.put(SVG_EVENT_ATTRS[i], SVG_DOM_EVENT[i]);
331             attrToListener.put(SVG_EVENT_ATTRS[i], listeners[i]);
332         }
333     }
334
335     /**
336      * Creates a new ScriptingEnvironment.
337      * @param ctx the bridge context
338      */

339     public ScriptingEnvironment(BridgeContext ctx) {
340         super(ctx);
341         updateManager = ctx.getUpdateManager();
342         updateRunnableQueue = updateManager.getUpdateRunnableQueue();
343         
344         // Add the scripting listeners.
345
addScriptingListeners(document.getDocumentElement());
346
347         // Add the listeners responsible of updating the event attributes
348
EventTarget JavaDoc et = (EventTarget JavaDoc)document;
349         et.addEventListener("DOMNodeInserted",
350                             domNodeInsertedListener,
351                             false);
352         et.addEventListener("DOMNodeRemoved",
353                             domNodeRemovedListener,
354                             false);
355         et.addEventListener("DOMAttrModified",
356                             domAttrModifiedListener,
357                             false);
358     }
359
360     /**
361      * Creates a new Window object.
362      */

363     public org.apache.batik.script.Window createWindow(Interpreter interp,
364                                                        String JavaDoc lang) {
365         return new Window(interp, lang);
366     }
367
368     /**
369      * Runs an event handler.
370      */

371     public void runEventHandler(String JavaDoc script, Event JavaDoc evt,
372                                 String JavaDoc lang, String JavaDoc desc) {
373         Interpreter interpreter = getInterpreter(lang);
374         if (interpreter == null)
375             return;
376
377         try {
378             checkCompatibleScriptURL(lang, docPURL);
379
380             interpreter.bindObject(EVENT_NAME, evt);
381             interpreter.bindObject(ALTERNATE_EVENT_NAME, evt);
382             interpreter.evaluate(new StringReader JavaDoc(script), desc);
383         } catch (IOException JavaDoc ioe) {
384             // Do nothing, can't really happen with StringReader
385
} catch (InterpreterException ie) {
386             handleInterpreterException(ie);
387         } catch (SecurityException JavaDoc se) {
388             handleSecurityException(se);
389         }
390     }
391
392     /**
393      * Interrupts the periodic tasks and dispose this ScriptingEnvironment.
394      */

395     public void interrupt() {
396         timer.cancel();
397         // Remove the scripting listeners.
398
removeScriptingListeners(document.getDocumentElement());
399
400         // Remove the listeners responsible of updating the event attributes
401
EventTarget JavaDoc et = (EventTarget JavaDoc)document;
402         et.removeEventListener("DOMNodeInserted",
403                                domNodeInsertedListener,
404                                false);
405         et.removeEventListener("DOMNodeRemoved",
406                                domNodeRemovedListener,
407                                false);
408         et.removeEventListener("DOMAttrModified",
409                                domAttrModifiedListener,
410                                false);
411     }
412
413     /**
414      * Adds the scripting listeners to the given element.
415      */

416     protected void addScriptingListeners(Node JavaDoc node) {
417         if (node.getNodeType() == Node.ELEMENT_NODE) {
418             // Attach the listeners
419
Element JavaDoc elt = (Element JavaDoc)node;
420             EventTarget JavaDoc target = (EventTarget JavaDoc)elt;
421             if (SVGConstants.SVG_NAMESPACE_URI.equals(elt.getNamespaceURI())) {
422                 if (SVGConstants.SVG_SVG_TAG.equals(elt.getLocalName())) {
423                     // <svg> listeners
424
if (elt.hasAttributeNS(null, "onabort")) {
425                         target.addEventListener("SVGAbort",
426                                                 svgAbortListener, false);
427                     }
428                     if (elt.hasAttributeNS(null, "onerror")) {
429                         target.addEventListener("SVGError",
430                                                 svgErrorListener, false);
431                     }
432                     if (elt.hasAttributeNS(null, "onresize")) {
433                         target.addEventListener("SVGResize",
434                                                 svgResizeListener, false);
435                     }
436                     if (elt.hasAttributeNS(null, "onscroll")) {
437                         target.addEventListener("SVGScroll",
438                                             svgScrollListener, false);
439                     }
440                     if (elt.hasAttributeNS(null, "onunload")) {
441                         target.addEventListener("SVGUnload",
442                                                 svgUnloadListener, false);
443                     }
444                     if (elt.hasAttributeNS(null, "onzoom")) {
445                         target.addEventListener("SVGZoom",
446                                                 svgZoomListener, false);
447                     }
448                 } else {
449                     String JavaDoc name = elt.getLocalName();
450                     if (name.equals(SVGConstants.SVG_SET_TAG) ||
451                         name.startsWith("animate")) {
452                         // animation listeners
453
if (elt.hasAttributeNS(null, "onbegin")) {
454                             target.addEventListener("beginEvent",
455                                                     beginListener ,
456                                                     false);
457                         }
458                         if (elt.hasAttributeNS(null, "onend")) {
459                             target.addEventListener("endEvent",
460                                                     endListener,
461                                                     false);
462                         }
463                         if (elt.hasAttributeNS(null, "onrepeat")) {
464                             target.addEventListener("repeatEvent",
465                                                     repeatListener ,
466                                                     false);
467                         }
468                         return;
469                     }
470                 }
471             }
472
473             // UI listeners
474
if (elt.hasAttributeNS(null, "onfocusin")) {
475                 target.addEventListener("DOMFocusIn", focusinListener, false);
476             }
477             if (elt.hasAttributeNS(null, "onfocusout")) {
478                 target.addEventListener("DOMFocusOut", focusoutListener,
479                                         false);
480             }
481             if (elt.hasAttributeNS(null, "onactivate")) {
482                 target.addEventListener("DOMActivate", activateListener,
483                                         false);
484             }
485             if (elt.hasAttributeNS(null, "onclick")) {
486                 target.addEventListener("click", clickListener, false);
487             }
488             if (elt.hasAttributeNS(null, "onmousedown")) {
489                 target.addEventListener("mousedown", mousedownListener, false);
490             }
491             if (elt.hasAttributeNS(null, "onmouseup")) {
492                 target.addEventListener("mouseup", mouseupListener, false);
493             }
494             if (elt.hasAttributeNS(null, "onmouseover")) {
495                 target.addEventListener("mouseover", mouseoverListener, false);
496             }
497             if (elt.hasAttributeNS(null, "onmouseout")) {
498                 target.addEventListener("mouseout", mouseoutListener, false);
499             }
500             if (elt.hasAttributeNS(null, "onmousemove")) {
501                 target.addEventListener("mousemove", mousemoveListener, false);
502             }
503             if (elt.hasAttributeNS(null, "onkeypress")) {
504                 target.addEventListener("keypress", keypressListener, false);
505             }
506             if (elt.hasAttributeNS(null, "onkeydown")) {
507                 target.addEventListener("keydown", keydownListener, false);
508             }
509             if (elt.hasAttributeNS(null, "onkeyup")) {
510                 target.addEventListener("keyup", keyupListener, false);
511             }
512         }
513
514         // Adds the listeners to the children
515
for (Node JavaDoc n = node.getFirstChild();
516              n != null;
517              n = n.getNextSibling()) {
518             addScriptingListeners(n);
519         }
520     }
521
522     /**
523      * Removes the scripting listeners from the given element.
524      */

525     protected void removeScriptingListeners(Node JavaDoc node) {
526         if (node.getNodeType() == Node.ELEMENT_NODE) {
527             // Detach the listeners
528
Element JavaDoc elt = (Element JavaDoc)node;
529             EventTarget JavaDoc target = (EventTarget JavaDoc)elt;
530             if (SVGConstants.SVG_NAMESPACE_URI.equals(elt.getNamespaceURI())) {
531                 if (SVGConstants.SVG_SVG_TAG.equals(elt.getLocalName())) {
532                     // <svg> listeners
533
target.removeEventListener("SVGAbort",
534                                                svgAbortListener, false);
535                     target.removeEventListener("SVGError",
536                                                svgErrorListener, false);
537                     target.removeEventListener("SVGResize",
538                                                svgResizeListener, false);
539                     target.removeEventListener("SVGScroll",
540                                                svgScrollListener, false);
541                     target.removeEventListener("SVGUnload",
542                                                svgUnloadListener, false);
543                     target.removeEventListener("SVGZoom",
544                                                svgZoomListener, false);
545                 } else {
546                     String JavaDoc name = elt.getLocalName();
547                     if (name.equals(SVGConstants.SVG_SET_TAG) ||
548                         name.startsWith("animate")) {
549                         // animation listeners
550
target.removeEventListener("beginEvent",
551                                                    beginListener ,
552                                                    false);
553                         target.removeEventListener("endEvent",
554                                                    endListener,
555                                                    false);
556                         target.removeEventListener("repeatEvent",
557                                                    repeatListener ,
558                                                    false);
559                         return;
560                     }
561                 }
562             }
563
564             // UI listeners
565
target.removeEventListener("DOMFocusIn", focusinListener, false);
566             target.removeEventListener("DOMFocusOut", focusoutListener, false);
567             target.removeEventListener("DOMActivate", activateListener, false);
568             target.removeEventListener("click", clickListener, false);
569             target.removeEventListener("mousedown", mousedownListener, false);
570             target.removeEventListener("mouseup", mouseupListener, false);
571             target.removeEventListener("mouseover", mouseoverListener, false);
572             target.removeEventListener("mouseout", mouseoutListener, false);
573             target.removeEventListener("mousemove", mousemoveListener, false);
574             target.removeEventListener("keypress", keypressListener, false);
575             target.removeEventListener("keydown", keydownListener, false);
576             target.removeEventListener("keyup", keyupListener, false);
577         }
578
579         // Removes the listeners from the children
580
for (Node JavaDoc n = node.getFirstChild();
581              n != null;
582              n = n.getNextSibling()) {
583             removeScriptingListeners(n);
584         }
585     }
586
587     /**
588      * Updates the registration of a listener on the given element.
589      */

590     protected void updateScriptingListeners(Element JavaDoc elt, String JavaDoc attr) {
591         String JavaDoc domEvt = (String JavaDoc) attrToDOMEvent.get(attr);
592         if (domEvt == null) return; // Not an event attr.
593
EventListener JavaDoc listener = (EventListener JavaDoc)attrToListener.get(attr);
594         EventTarget JavaDoc target = (EventTarget JavaDoc) elt;
595         if (elt.hasAttributeNS(null, attr))
596             target.addEventListener(domEvt, listener, false);
597         else
598             target.removeEventListener(domEvt, listener, false);
599     }
600     
601
602     /**
603      * To interpret a script.
604      */

605     protected class EvaluateRunnable implements Runnable JavaDoc {
606         protected Interpreter interpreter;
607         protected String JavaDoc script;
608         public EvaluateRunnable(String JavaDoc s, Interpreter interp) {
609             interpreter = interp;
610             script = s;
611         }
612         public void run() {
613             try {
614                 interpreter.evaluate(script);
615             } catch (InterpreterException ie) {
616                 handleInterpreterException(ie);
617             }
618         }
619     }
620
621     /**
622      * To interpret a script.
623      */

624     protected class EvaluateIntervalRunnable implements Runnable JavaDoc {
625         /**
626          * Incremented each time this runnable is added to the queue.
627          */

628         public int count;
629         public boolean error;
630
631         protected Interpreter interpreter;
632         protected String JavaDoc script;
633
634         public EvaluateIntervalRunnable(String JavaDoc s, Interpreter interp) {
635             interpreter = interp;
636             script = s;
637         }
638         public void run() {
639             synchronized (this) {
640                 if (error)
641                     return;
642                 count--;
643             }
644             try {
645                 interpreter.evaluate(script);
646             } catch (InterpreterException ie) {
647                 handleInterpreterException(ie);
648                 synchronized (this) {
649                     error = true;
650                 }
651             } catch (Exception JavaDoc e) {
652                 if (userAgent != null) {
653                     userAgent.displayError(e);
654                 } else {
655                     e.printStackTrace(); // No UA so just output...
656
}
657                 synchronized (this) {
658                     error = true;
659                 }
660             }
661         }
662     }
663
664     /**
665      * To call a Runnable.
666      */

667     protected class EvaluateRunnableRunnable implements Runnable JavaDoc {
668         /**
669          * Incremented each time this runnable is put in the queue.
670          */

671         public int count;
672         public boolean error;
673
674         protected Runnable JavaDoc runnable;
675
676         public EvaluateRunnableRunnable(Runnable JavaDoc r) {
677             runnable = r;
678         }
679         public void run() {
680             synchronized (this) {
681                 if (error)
682                     return;
683                 count--;
684             }
685             try {
686                 runnable.run();
687             } catch (Exception JavaDoc e) {
688                 if (userAgent != null) {
689                     userAgent.displayError(e);
690                 } else {
691                     e.printStackTrace(); // No UA so just output...
692
}
693                 synchronized (this) {
694                     error = true;
695                 }
696             }
697         }
698     }
699
700     /**
701      * Represents the window object of this environment.
702      */

703     protected class Window implements org.apache.batik.script.Window {
704
705         /**
706          * The associated interpreter.
707          */

708         protected Interpreter interpreter;
709
710         /**
711          * The associated language.
712          */

713         protected String JavaDoc language;
714
715         /**
716          * Creates a new Window for the given language.
717          */

718         public Window(Interpreter interp, String JavaDoc lang) {
719             interpreter = interp;
720             language = lang;
721         }
722
723         /**
724          * Implements {@link
725          * org.apache.batik.script.Window#setInterval(String,long)}.
726          */

727         public Object JavaDoc setInterval(final String JavaDoc script, long interval) {
728             TimerTask JavaDoc tt = new TimerTask JavaDoc() {
729                     EvaluateIntervalRunnable eir =
730                         new EvaluateIntervalRunnable(script, interpreter);
731                     public void run() {
732                         synchronized