org.apache.batik.bridge.BaseScriptingEnvironment Maven / Gradle / Ivy
The newest version!
/*
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.
*/
package org.apache.batik.bridge;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PushbackInputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.jar.Manifest;
import org.apache.batik.dom.AbstractElement;
import org.apache.batik.dom.events.AbstractEvent;
import org.apache.batik.dom.events.NodeEventTarget;
import org.apache.batik.dom.util.XLinkSupport;
import org.apache.batik.script.Interpreter;
import org.apache.batik.script.InterpreterException;
import org.apache.batik.script.ScriptEventWrapper;
import org.apache.batik.util.ParsedURL;
import org.apache.batik.util.SVGConstants;
import org.apache.batik.constants.XMLConstants;
import org.apache.batik.w3c.dom.Location;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.events.DocumentEvent;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.events.EventTarget;
import org.w3c.dom.svg.SVGDocument;
import org.w3c.dom.svg.SVGSVGElement;
import org.w3c.dom.svg.EventListenerInitializer;
/**
* This class is the base class for SVG scripting.
*
* @author Stephane Hillion
* @version $Id$
*/
public class BaseScriptingEnvironment {
/**
* Constant used to describe inline scripts.
*
* {0} - URL of document containing script.
* {1} - Element tag
* {2} - line number of element.
*
*/
public static final String INLINE_SCRIPT_DESCRIPTION
= "BaseScriptingEnvironment.constant.inline.script.description";
/**
* Constant used to describe inline scripts.
*
* {0} - URL of document containing script.
* {1} - Event attribute name
* {2} - line number of element.
*
*/
public static final String EVENT_SCRIPT_DESCRIPTION
= "BaseScriptingEnvironment.constant.event.script.description";
/**
* Tells whether the given SVG document is dynamic.
*/
public static boolean isDynamicDocument(BridgeContext ctx, Document doc) {
Element elt = doc.getDocumentElement();
if ((elt != null) &&
SVGConstants.SVG_NAMESPACE_URI.equals(elt.getNamespaceURI())) {
if (elt.getAttributeNS
(null, SVGConstants.SVG_ONABORT_ATTRIBUTE).length() > 0) {
return true;
}
if (elt.getAttributeNS
(null, SVGConstants.SVG_ONERROR_ATTRIBUTE).length() > 0) {
return true;
}
if (elt.getAttributeNS
(null, SVGConstants.SVG_ONRESIZE_ATTRIBUTE).length() > 0) {
return true;
}
if (elt.getAttributeNS
(null, SVGConstants.SVG_ONUNLOAD_ATTRIBUTE).length() > 0) {
return true;
}
if (elt.getAttributeNS
(null, SVGConstants.SVG_ONSCROLL_ATTRIBUTE).length() > 0) {
return true;
}
if (elt.getAttributeNS
(null, SVGConstants.SVG_ONZOOM_ATTRIBUTE).length() > 0) {
return true;
}
return isDynamicElement(ctx, doc.getDocumentElement());
}
return false;
}
public static boolean isDynamicElement(BridgeContext ctx, Element elt) {
List bridgeExtensions = ctx.getBridgeExtensions(elt.getOwnerDocument());
return isDynamicElement(elt, ctx, bridgeExtensions);
}
/**
* Tells whether the given SVG element is dynamic.
*/
public static boolean isDynamicElement
(Element elt, BridgeContext ctx, List bridgeExtensions) {
for (Object bridgeExtension1 : bridgeExtensions) {
BridgeExtension bridgeExtension = (BridgeExtension) bridgeExtension1;
if (bridgeExtension.isDynamicElement(elt)) {
return true;
}
}
if (SVGConstants.SVG_NAMESPACE_URI.equals(elt.getNamespaceURI())) {
if (elt.getAttributeNS
(null, SVGConstants.SVG_ONKEYUP_ATTRIBUTE).length() > 0) {
return true;
}
if (elt.getAttributeNS
(null, SVGConstants.SVG_ONKEYDOWN_ATTRIBUTE).length() > 0) {
return true;
}
if (elt.getAttributeNS
(null, SVGConstants.SVG_ONKEYPRESS_ATTRIBUTE).length() > 0) {
return true;
}
if (elt.getAttributeNS
(null, SVGConstants.SVG_ONLOAD_ATTRIBUTE).length() > 0) {
return true;
}
if (elt.getAttributeNS
(null, SVGConstants.SVG_ONERROR_ATTRIBUTE).length() > 0) {
return true;
}
if (elt.getAttributeNS
(null, SVGConstants.SVG_ONACTIVATE_ATTRIBUTE).length() > 0) {
return true;
}
if (elt.getAttributeNS
(null, SVGConstants.SVG_ONCLICK_ATTRIBUTE).length() > 0) {
return true;
}
if (elt.getAttributeNS
(null, SVGConstants.SVG_ONFOCUSIN_ATTRIBUTE).length() > 0) {
return true;
}
if (elt.getAttributeNS
(null, SVGConstants.SVG_ONFOCUSOUT_ATTRIBUTE).length() > 0) {
return true;
}
if (elt.getAttributeNS
(null, SVGConstants.SVG_ONMOUSEDOWN_ATTRIBUTE).length() > 0) {
return true;
}
if (elt.getAttributeNS
(null, SVGConstants.SVG_ONMOUSEMOVE_ATTRIBUTE).length() > 0) {
return true;
}
if (elt.getAttributeNS
(null, SVGConstants.SVG_ONMOUSEOUT_ATTRIBUTE).length() > 0) {
return true;
}
if (elt.getAttributeNS
(null, SVGConstants.SVG_ONMOUSEOVER_ATTRIBUTE).length() > 0) {
return true;
}
if (elt.getAttributeNS
(null, SVGConstants.SVG_ONMOUSEUP_ATTRIBUTE).length() > 0) {
return true;
}
}
for (Node n = elt.getFirstChild();
n != null;
n = n.getNextSibling()) {
if (n.getNodeType() == Node.ELEMENT_NODE) {
if (isDynamicElement(ctx, (Element)n)) {
return true;
}
}
}
return false;
}
protected static final String EVENT_NAME = "event";
protected static final String ALTERNATE_EVENT_NAME = "evt";
/**
* The 'application/ecmascript' MIME type.
*/
protected static final String APPLICATION_ECMASCRIPT =
"application/ecmascript";
/**
* The bridge context.
*/
protected BridgeContext bridgeContext;
/**
* The user-agent.
*/
protected UserAgent userAgent;
/**
* The document to manage.
*/
protected Document document;
/**
* The URL of the document ot manage
*/
protected ParsedURL docPURL;
protected Set languages = new HashSet();
/**
* The default Interpreter for the document
*/
protected Interpreter interpreter;
/**
* Map of {@link Interpreter} to {@link org.apache.batik.bridge.Window}
* objects.
*/
protected Map windowObjects = new HashMap();
/**
* Set of <script> elements that have already been executed.
*/
protected WeakHashMap executedScripts = new WeakHashMap();
/**
* Creates a new BaseScriptingEnvironment.
* @param ctx the bridge context
*/
public BaseScriptingEnvironment(BridgeContext ctx) {
bridgeContext = ctx;
document = ctx.getDocument();
docPURL = new ParsedURL(((SVGDocument)document).getURL());
userAgent = bridgeContext.getUserAgent();
}
/**
* Returns the Window object for the specified {@link Interpreter}.
*/
public org.apache.batik.bridge.Window getWindow(Interpreter interp,
String lang) {
org.apache.batik.bridge.Window w =
(org.apache.batik.bridge.Window) windowObjects.get(interp);
if (w == null) {
w = interp == null ? new Window(null, null)
: createWindow(interp, lang);
windowObjects.put(interp, w);
}
return w;
}
/**
* Returns the Window object for scripting languages that have no
* {@link Interpreter} object.
*/
public org.apache.batik.bridge.Window getWindow() {
return getWindow(null, null);
}
/**
* Creates a new Window object.
*/
protected org.apache.batik.bridge.Window createWindow(Interpreter interp,
String lang) {
return new Window(interp, lang);
}
/**
* Returns the default Interpreter for this document.
*/
public Interpreter getInterpreter() {
if (interpreter != null)
return interpreter;
SVGSVGElement root = (SVGSVGElement)document.getDocumentElement();
String lang = root.getContentScriptType();
return getInterpreter(lang);
}
public Interpreter getInterpreter(String lang) {
interpreter = bridgeContext.getInterpreter(lang);
if (interpreter == null) {
if (languages.contains(lang)) {
// Already issued warning so just return null.
return null;
}
// So we know we have processed this interpreter.
languages.add(lang);
return null;
}
if (!languages.contains(lang)) {
languages.add(lang);
initializeEnvironment(interpreter, lang);
}
return interpreter;
}
/**
* Initializes the environment of the given interpreter.
*/
public void initializeEnvironment(Interpreter interp, String lang) {
interp.bindObject("window", getWindow(interp, lang));
}
/**
* Loads the scripts contained in the <script> elements.
*/
public void loadScripts() {
NodeList scripts = document.getElementsByTagNameNS
(SVGConstants.SVG_NAMESPACE_URI, SVGConstants.SVG_SCRIPT_TAG);
int len = scripts.getLength();
for (int i = 0; i < len; i++) {
AbstractElement script = (AbstractElement) scripts.item(i);
loadScript(script);
}
}
/**
* Executes the specified <script> element, if it hasn't been
* executed already.
*/
protected void loadScript(AbstractElement script) {
// Don't execute