0001: package com.meterware.httpunit.javascript;
0002:
0003: /********************************************************************************************************************
0004: * $Id: JavaScript.java,v 1.63 2004/12/02 03:43:20 russgold Exp $
0005: *
0006: * Copyright (c) 2002-2004, Russell Gold
0007: *
0008: * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
0009: * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
0010: * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
0011: * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
0012: *
0013: * The above copyright notice and this permission notice shall be included in all copies or substantial portions
0014: * of the Software.
0015: *
0016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
0017: * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
0018: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
0019: * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
0020: * DEALINGS IN THE SOFTWARE.
0021: *
0022: *******************************************************************************************************************/
0023: import com.meterware.httpunit.*;
0024:
0025: import com.meterware.httpunit.scripting.*;
0026:
0027: import java.lang.reflect.InvocationTargetException;
0028: import java.util.ArrayList;
0029: import java.io.IOException;
0030: import java.net.URL;
0031:
0032: import org.mozilla.javascript.*;
0033: import org.xml.sax.SAXException;
0034:
0035: /**
0036: * This class is the Rhino-compatible implementation of the JavaScript DOM objects.
0037: *
0038: * @author <a href="mailto:russgold@httpunit.org">Russell Gold</a>
0039: **/
0040: public class JavaScript {
0041:
0042: private final static Object[] NO_ARGS = new Object[0];
0043:
0044: private static boolean _throwExceptionsOnError = true;
0045:
0046: private static ArrayList _errorMessages = new ArrayList();
0047:
0048: static boolean isThrowExceptionsOnError() {
0049: return _throwExceptionsOnError;
0050: }
0051:
0052: static void setThrowExceptionsOnError(boolean throwExceptionsOnError) {
0053: _throwExceptionsOnError = throwExceptionsOnError;
0054: }
0055:
0056: static void clearErrorMessages() {
0057: _errorMessages.clear();
0058: }
0059:
0060: static String[] getErrorMessages() {
0061: return (String[]) _errorMessages
0062: .toArray(new String[_errorMessages.size()]);
0063: }
0064:
0065: /**
0066: * Initiates JavaScript execution for the specified web response.
0067: */
0068: static void run(WebResponse response)
0069: throws IllegalAccessException, InstantiationException,
0070: InvocationTargetException, ClassDefinitionException,
0071: NotAFunctionException, PropertyException, SAXException,
0072: JavaScriptException {
0073: Context context = Context.enter();
0074: Scriptable scope = context.initStandardObjects(null);
0075: initHTMLObjects(scope);
0076:
0077: Window w = (Window) context.newObject(scope, "Window");
0078: w.initialize(null, response.getScriptableObject());
0079: }
0080:
0081: /**
0082: * Runs the onload event for the specified web response.
0083: */
0084: public static void load(WebResponse response)
0085: throws ClassDefinitionException, InstantiationException,
0086: IllegalAccessException, InvocationTargetException,
0087: PropertyException, JavaScriptException, SAXException,
0088: NotAFunctionException {
0089: if (!(response.getScriptableObject().getScriptEngine() instanceof JavaScriptEngine))
0090: run(response);
0091: response.getScriptableObject().load();
0092: }
0093:
0094: private static void initHTMLObjects(Scriptable scope)
0095: throws IllegalAccessException, InstantiationException,
0096: InvocationTargetException, ClassDefinitionException,
0097: PropertyException {
0098: ScriptableObject.defineClass(scope, Window.class);
0099: ScriptableObject.defineClass(scope, Document.class);
0100: ScriptableObject.defineClass(scope, Style.class);
0101: ScriptableObject.defineClass(scope, Location.class);
0102: ScriptableObject.defineClass(scope, Navigator.class);
0103: ScriptableObject.defineClass(scope, Screen.class);
0104: ScriptableObject.defineClass(scope, Link.class);
0105: ScriptableObject.defineClass(scope, Form.class);
0106: ScriptableObject.defineClass(scope, Control.class);
0107: ScriptableObject.defineClass(scope, Link.class);
0108: ScriptableObject.defineClass(scope, Image.class);
0109: ScriptableObject.defineClass(scope, Options.class);
0110: ScriptableObject.defineClass(scope, Option.class);
0111: ScriptableObject.defineClass(scope, ElementArray.class);
0112: ScriptableObject.defineClass(scope, HTMLElement.class);
0113: }
0114:
0115: abstract static class JavaScriptEngine extends ScriptableObject
0116: implements ScriptingEngine {
0117:
0118: protected ScriptableDelegate _scriptable;
0119: protected JavaScriptEngine _parent;
0120:
0121: public boolean supportsScriptLanguage(String language) {
0122: return language == null
0123: || language.toLowerCase().startsWith("javascript");
0124: }
0125:
0126: public String executeScript(String language, String script) {
0127: if (!supportsScriptLanguage(language))
0128: return "";
0129: try {
0130: script = script.trim();
0131: if (script.startsWith("<!--")) {
0132: script = withoutFirstLine(script);
0133: if (script.endsWith("-->"))
0134: script = script.substring(0, script
0135: .lastIndexOf("-->"));
0136: }
0137: Context.getCurrentContext().evaluateString(this ,
0138: script, "httpunit", 0, null);
0139: StringBuffer buffer = getDocumentWriteBuffer();
0140: return buffer.toString();
0141: } catch (Exception e) {
0142: handleScriptException(e, "Script '" + script + "'");
0143: return "";
0144: } finally {
0145: discardDocumentWriteBuffer();
0146: }
0147: }
0148:
0149: protected StringBuffer getDocumentWriteBuffer() {
0150: throw new IllegalStateException(
0151: "may not run executeScript() from " + getClass());
0152: }
0153:
0154: protected void discardDocumentWriteBuffer() {
0155: throw new IllegalStateException(
0156: "may not run executeScript() from " + getClass());
0157: }
0158:
0159: private String withoutFirstLine(String script) {
0160: for (int i = 0; i < script.length(); i++) {
0161: if (isLineTerminator(script.charAt(i)))
0162: return script.substring(i).trim();
0163: }
0164: return "";
0165: }
0166:
0167: private boolean isLineTerminator(char c) {
0168: return c == 0x0A || c == 0x0D;
0169: }
0170:
0171: public boolean performEvent(String eventScript) {
0172: try {
0173: final Context context = Context.getCurrentContext();
0174: context.setOptimizationLevel(-1);
0175: Function f = context.compileFunction(this ,
0176: "function x() { " + eventScript + "}",
0177: "httpunit", 0, null);
0178: Object result = f.call(context, this , this , NO_ARGS);
0179: return (result instanceof Boolean) ? ((Boolean) result)
0180: .booleanValue() : true;
0181: } catch (Exception e) {
0182: handleScriptException(e, "Event '" + eventScript + "'");
0183: return false;
0184: }
0185: }
0186:
0187: /**
0188: * Evaluates the specified string as JavaScript. Will return null if the script has no return value.
0189: */
0190: public String evaluateScriptExpression(String urlString) {
0191: try {
0192: Object result = Context.getCurrentContext()
0193: .evaluateString(this , urlString, "httpunit", 0,
0194: null);
0195: return (result == null || result instanceof Undefined) ? null
0196: : result.toString();
0197: } catch (Exception e) {
0198: handleScriptException(e, "URL '" + urlString + "'");
0199: return null;
0200: }
0201: }
0202:
0203: private void handleScriptException(Exception e, String badScript) {
0204: final String errorMessage = badScript + " failed: " + e;
0205: if (!(e instanceof EcmaError)
0206: && !(e instanceof EvaluatorException)) {
0207: e.printStackTrace();
0208: throw new RuntimeException(errorMessage);
0209: } else if (isThrowExceptionsOnError()) {
0210: e.printStackTrace();
0211: throw new ScriptException(errorMessage);
0212: } else {
0213: _errorMessages.add(errorMessage);
0214: }
0215: }
0216:
0217: void initialize(JavaScriptEngine parent,
0218: ScriptableDelegate scriptable) throws SAXException,
0219: PropertyException, JavaScriptException,
0220: NotAFunctionException {
0221: _scriptable = scriptable;
0222: _scriptable.setScriptEngine(this );
0223: _parent = parent;
0224: if (parent != null)
0225: setParentScope(parent);
0226: }
0227:
0228: String getName() {
0229: return _scriptable instanceof NamedDelegate ? ((NamedDelegate) _scriptable)
0230: .getName()
0231: : "";
0232: }
0233:
0234: String getID() {
0235: return _scriptable instanceof IdentifiedDelegate ? ((IdentifiedDelegate) _scriptable)
0236: .getID()
0237: : "";
0238: }
0239:
0240: public boolean has(String propertyName, Scriptable scriptable) {
0241: return super .has(propertyName, scriptable)
0242: || (_scriptable != null && _scriptable
0243: .get(propertyName) != null);
0244: }
0245:
0246: public Object get(String propertyName, Scriptable scriptable) {
0247: Object result = super .get(propertyName, scriptable);
0248: if (result != NOT_FOUND)
0249: return result;
0250: if (_scriptable == null)
0251: return NOT_FOUND;
0252:
0253: return convertIfNeeded(_scriptable.get(propertyName));
0254:
0255: }
0256:
0257: public Object get(int i, Scriptable scriptable) {
0258: Object result = super .get(i, scriptable);
0259: if (result != NOT_FOUND)
0260: return result;
0261: if (_scriptable == null)
0262: return NOT_FOUND;
0263:
0264: return convertIfNeeded(_scriptable.get(i));
0265: }
0266:
0267: private Object convertIfNeeded(final Object property) {
0268: if (property == null)
0269: return NOT_FOUND;
0270:
0271: if (property instanceof ScriptableDelegate[])
0272: return toScriptable((ScriptableDelegate[]) property);
0273: if (!(property instanceof ScriptableDelegate))
0274: return property;
0275: return toScriptable((ScriptableDelegate) property);
0276: }
0277:
0278: private Object toScriptable(ScriptableDelegate[] list) {
0279: Object[] delegates = new Object[list.length];
0280: for (int i = 0; i < delegates.length; i++) {
0281: delegates[i] = toScriptable(list[i]);
0282: }
0283: return Context.getCurrentContext()
0284: .newArray(this , delegates);
0285: }
0286:
0287: public void put(String propertyName, Scriptable scriptable,
0288: Object value) {
0289: if (_scriptable == null
0290: || _scriptable.get(propertyName) == null) {
0291: super .put(propertyName, scriptable, value);
0292: } else {
0293: _scriptable.set(propertyName, value);
0294: }
0295: }
0296:
0297: public String toString() {
0298: return (_scriptable == null ? "prototype " : "")
0299: + getClassName();
0300: }
0301:
0302: public ScriptingEngine newScriptingEngine(
0303: ScriptableDelegate child) {
0304: try {
0305: return (ScriptingEngine) toScriptable(child);
0306: } catch (Exception e) {
0307: e.printStackTrace();
0308: throw new RuntimeException(e.toString());
0309: }
0310: }
0311:
0312: public void clearCaches() {
0313: }
0314:
0315: protected static String toStringIfNotUndefined(Object object) {
0316: return (object == null || Undefined.instance.equals(object)) ? null
0317: : object.toString();
0318: }
0319:
0320: /**
0321: * Converts a scriptable delegate obtained from a subobject into the appropriate Rhino-compatible Scriptable.
0322: **/
0323: final Object toScriptable(ScriptableDelegate delegate) {
0324: if (delegate == null) {
0325: return NOT_FOUND;
0326: } else if (delegate.getScriptEngine() instanceof Scriptable) {
0327: return (Scriptable) delegate.getScriptEngine();
0328: } else {
0329: try {
0330: JavaScriptEngine element = (JavaScriptEngine) Context
0331: .getCurrentContext().newObject(this ,
0332: getScriptableClassName(delegate));
0333: element.initialize(this , delegate);
0334: return element;
0335: } catch (RuntimeException e) {
0336: throw e;
0337: } catch (Exception e) {
0338: throw new RhinoException(e);
0339: }
0340: }
0341: }
0342:
0343: private String getScriptableClassName(
0344: ScriptableDelegate delegate) {
0345: if (delegate instanceof WebResponse.Scriptable)
0346: return "Window";
0347: if (delegate instanceof HTMLPage.Scriptable)
0348: return "Document";
0349: if (delegate instanceof WebForm.Scriptable)
0350: return "Form";
0351: if (delegate instanceof WebLink.Scriptable)
0352: return "Link";
0353: if (delegate instanceof WebImage.Scriptable)
0354: return "Image";
0355: if (delegate instanceof SelectionOptions)
0356: return "Options";
0357: if (delegate instanceof SelectionOption)
0358: return "Option";
0359: if (delegate instanceof Input)
0360: return "Control";
0361: if (delegate instanceof DocumentElement)
0362: return "HTMLElement";
0363:
0364: throw new IllegalArgumentException(
0365: "Unknown ScriptableDelegate class: "
0366: + delegate.getClass());
0367: }
0368:
0369: protected ElementArray toElementArray(
0370: ScriptableDelegate[] scriptables) {
0371: JavaScriptEngine[] elements = new JavaScriptEngine[scriptables.length];
0372: for (int i = 0; i < elements.length; i++) {
0373: elements[i] = (JavaScriptEngine) toScriptable(scriptables[i]);
0374: }
0375: ElementArray result = ElementArray.newElementArray(this );
0376: result.initialize(elements);
0377: return result;
0378: }
0379:
0380: }
0381:
0382: static public class Window extends JavaScriptEngine {
0383:
0384: private Document _document;
0385: private Navigator _navigator;
0386: private Location _location;
0387: private Screen _screen;
0388: private ElementArray _frames;
0389:
0390: public String getClassName() {
0391: return "Window";
0392: }
0393:
0394: public Window jsGet_window() {
0395: return this ;
0396: }
0397:
0398: public Window jsGet_self() {
0399: return this ;
0400: }
0401:
0402: public Document jsGet_document() {
0403: if (_document == null) {
0404: _document = (Document) toScriptable(getDelegate()
0405: .getDocument());
0406: }
0407: return _document;
0408: }
0409:
0410: public Scriptable jsGet_frames() throws SAXException,
0411: PropertyException, JavaScriptException,
0412: NotAFunctionException {
0413: if (_frames == null) {
0414: WebResponse.Scriptable scriptables[] = getDelegate()
0415: .getFrames();
0416: Window[] frames = new Window[scriptables.length];
0417: for (int i = 0; i < frames.length; i++) {
0418: frames[i] = (Window) toScriptable(scriptables[i]);
0419: }
0420: _frames = (ElementArray) Context.getCurrentContext()
0421: .newObject(this , "ElementArray");
0422: _frames.initialize(frames);
0423: }
0424: return _frames;
0425: }
0426:
0427: public Navigator jsGet_navigator() {
0428: return _navigator;
0429: }
0430:
0431: public Screen jsGet_screen() {
0432: return _screen;
0433: }
0434:
0435: public Location jsGet_location() {
0436: return _location;
0437: }
0438:
0439: public void jsSet_location(String relativeURL)
0440: throws IOException, SAXException {
0441: setLocation(relativeURL);
0442: }
0443:
0444: void setLocation(String relativeURL) throws IOException,
0445: SAXException {
0446: getDelegate().setLocation(relativeURL);
0447: }
0448:
0449: void initialize(JavaScriptEngine parent,
0450: ScriptableDelegate scriptable)
0451: throws JavaScriptException, NotAFunctionException,
0452: PropertyException, SAXException {
0453: super .initialize(parent, scriptable);
0454:
0455: _location = (Location) Context.getCurrentContext()
0456: .newObject(this , "Location");
0457: _location.initialize(this ,
0458: ((WebResponse.Scriptable) scriptable).getURL());
0459:
0460: _navigator = (Navigator) Context.getCurrentContext()
0461: .newObject(this , "Navigator");
0462: _navigator.setClientProperties(getDelegate()
0463: .getClientProperties());
0464:
0465: _screen = (Screen) Context.getCurrentContext().newObject(
0466: this , "Screen");
0467: _screen.setClientProperties(getDelegate()
0468: .getClientProperties());
0469: }
0470:
0471: public void jsFunction_alert(String message) {
0472: getDelegate().alert(message);
0473: }
0474:
0475: public boolean jsFunction_confirm(String message) {
0476: return getDelegate().getConfirmationResponse(message);
0477: }
0478:
0479: public String jsFunction_prompt(String message,
0480: String defaultResponse) {
0481: return getDelegate().getUserResponse(message,
0482: defaultResponse);
0483: }
0484:
0485: public void jsFunction_moveTo(int x, int y) {
0486: }
0487:
0488: public void jsFunction_focus() {
0489: }
0490:
0491: public void jsFunction_setTimeout() {
0492: }
0493:
0494: public void jsFunction_close() {
0495: getDelegate().close();
0496: }
0497:
0498: public Window jsFunction_open(Object url, String name,
0499: String features, boolean replace)
0500: throws PropertyException, JavaScriptException,
0501: NotAFunctionException, IOException, SAXException {
0502: WebResponse.Scriptable delegate = getDelegate().open(
0503: toStringIfNotUndefined(url), name, features,
0504: replace);
0505: return delegate == null ? null
0506: : (Window) toScriptable(delegate);
0507: }
0508:
0509: public void clearCaches() {
0510: if (_document != null)
0511: _document.clearCaches();
0512: }
0513:
0514: protected StringBuffer getDocumentWriteBuffer() {
0515: return jsGet_document().getWriteBuffer();
0516: }
0517:
0518: protected void discardDocumentWriteBuffer() {
0519: jsGet_document().clearWriteBuffer();
0520: }
0521:
0522: private WebResponse.Scriptable getDelegate() {
0523: return (WebResponse.Scriptable) _scriptable;
0524: }
0525: }
0526:
0527: static public class Document extends JavaScriptEngine {
0528:
0529: private ElementArray _forms;
0530: private ElementArray _links;
0531: private ElementArray _images;
0532: private StringBuffer _writeBuffer;
0533: private String _mimeType;
0534:
0535: public String getClassName() {
0536: return "Document";
0537: }
0538:
0539: public void clearCaches() {
0540: _forms = _links = _images = null;
0541: }
0542:
0543: public String jsGet_title() throws SAXException {
0544: return getDelegate().getTitle();
0545: }
0546:
0547: public Scriptable jsGet_images() throws SAXException {
0548: if (_images == null)
0549: _images = toElementArray(getDelegate().getImages());
0550: return _images;
0551: }
0552:
0553: public Scriptable jsGet_links() throws SAXException {
0554: if (_links == null)
0555: _links = toElementArray(getDelegate().getLinks());
0556: return _links;
0557: }
0558:
0559: public Scriptable jsGet_forms() throws SAXException {
0560: if (_forms == null)
0561: _forms = toElementArray(getDelegate().getForms());
0562: return _forms;
0563: }
0564:
0565: public Object jsFunction_getElementById(String id) {
0566: ScriptableDelegate elementWithID = getDelegate()
0567: .getElementWithID(id);
0568: return elementWithID == null ? null
0569: : toScriptable(elementWithID);
0570: }
0571:
0572: public Object jsFunction_getElementsByName(String name) {
0573: return toElementArray(getDelegate().getElementsByName(name));
0574: }
0575:
0576: public Object jsFunction_getElementsByTagName(String name) {
0577: return toElementArray(getDelegate().getElementsByTagName(
0578: name));
0579: }
0580:
0581: public Object jsGet_location() {
0582: return _parent == null ? NOT_FOUND : getWindow()
0583: .jsGet_location();
0584: }
0585:
0586: public void jsSet_location(String urlString)
0587: throws IOException, SAXException {
0588: if (urlString.startsWith("color"))
0589: return;
0590: getWindow().setLocation(urlString);
0591: }
0592:
0593: public String jsGet_cookie() {
0594: return getDelegate().getCookie();
0595: }
0596:
0597: public void jsSet_cookie(String cookieSpec) {
0598: final int equalsIndex = cookieSpec.indexOf('=');
0599: if (equalsIndex < 0)
0600: return;
0601: int endIndex = cookieSpec.indexOf(";", equalsIndex);
0602: if (endIndex < 0)
0603: endIndex = cookieSpec.length();
0604: String name = cookieSpec.substring(0, equalsIndex);
0605: String value = cookieSpec.substring(equalsIndex + 1,
0606: endIndex);
0607: getDelegate().setCookie(name, value);
0608: }
0609:
0610: private Window getWindow() {
0611: return ((Window) _parent);
0612: }
0613:
0614: public void jsFunction_open(Object mimeType) {
0615: _mimeType = toStringIfNotUndefined(mimeType);
0616: }
0617:
0618: public void jsFunction_close() {
0619: if (getDelegate().replaceText(getWriteBuffer().toString(),
0620: _mimeType == null ? "text/html" : _mimeType)) {
0621: getWriteBuffer().setLength(0);
0622: }
0623: }
0624:
0625: public void jsFunction_write(String string) {
0626: getWriteBuffer().append(string);
0627: }
0628:
0629: public void jsFunction_writeln(String string) {
0630: getWriteBuffer().append(string).append((char) 0x0D).append(
0631: (char) 0x0A);
0632: }
0633:
0634: protected StringBuffer getWriteBuffer() {
0635: if (_writeBuffer == null)
0636: _writeBuffer = new StringBuffer();
0637: return _writeBuffer;
0638: }
0639:
0640: protected void clearWriteBuffer() {
0641: _writeBuffer = null;
0642: }
0643:
0644: private HTMLPage.Scriptable getDelegate() {
0645: return (HTMLPage.Scriptable) _scriptable;
0646: }
0647:
0648: }
0649:
0650: static public class Location extends JavaScriptEngine {
0651:
0652: private URL _url;
0653: private Window _window;
0654:
0655: public String getClassName() {
0656: return "Location";
0657: }
0658:
0659: void initialize(Window window, URL url) {
0660: _window = window;
0661: _url = url;
0662: }
0663:
0664: public void jsFunction_replace(String urlString)
0665: throws IOException, SAXException {
0666: _window.setLocation(urlString);
0667: }
0668:
0669: public String jsGet_href() {
0670: return toString();
0671: }
0672:
0673: public void jsSet_href(String urlString) throws SAXException,
0674: IOException {
0675: _window.setLocation(urlString);
0676: }
0677:
0678: public String jsGet_protocol() {
0679: return _url.getProtocol() + ':';
0680: }
0681:
0682: public String jsGet_host() {
0683: return _url.getHost() + ':' + _url.getPort();
0684: }
0685:
0686: public String jsGet_hostname() {
0687: return _url.getHost();
0688: }
0689:
0690: public String jsGet_port() {
0691: return String.valueOf(_url.getPort());
0692: }
0693:
0694: public String jsGet_pathname() {
0695: return _url.getPath();
0696: }
0697:
0698: public void jsSet_pathname(String newPath) throws SAXException,
0699: IOException {
0700: if (!newPath.startsWith("/"))
0701: newPath = '/' + newPath;
0702: URL newURL = new URL(_url, newPath);
0703: _window.setLocation(newURL.toExternalForm());
0704: }
0705:
0706: public String jsGet_search() {
0707: return '?' + _url.getQuery();
0708: }
0709:
0710: public void jsSet_search(String newSearch) throws SAXException,
0711: IOException {
0712: if (!newSearch.startsWith("?"))
0713: newSearch = '?' + newSearch;
0714: _window.setLocation(jsGet_protocol() + "//" + jsGet_host()
0715: + jsGet_pathname() + newSearch);
0716: }
0717:
0718: /**
0719: * Returns the default value of this scriptable object. In this case, it returns simply the URL as a string.
0720: * Note that this method is necessary, since Rhino will only call the toString method directly if there are no
0721: * Rhino methods defined (jsGet_*, jsFunction_*, etc.)
0722: */
0723: public Object getDefaultValue(Class typeHint) {
0724: return _url.toExternalForm();
0725: }
0726:
0727: public String toString() {
0728: return _url.toExternalForm();
0729: }
0730:
0731: }
0732:
0733: static public class Style extends JavaScriptEngine {
0734:
0735: private String _display = "inline";
0736: private String _visibility = "visible";
0737:
0738: public String getClassName() {
0739: return "Style";
0740: }
0741:
0742: public String jsGet_display() {
0743: return _display;
0744: }
0745:
0746: public void jsSet_display(String display) {
0747: _display = display;
0748: }
0749:
0750: public String jsGet_visibility() {
0751: return _visibility;
0752: }
0753:
0754: public void jsSet_visibility(String visibility) {
0755: _visibility = visibility;
0756: }
0757: }
0758:
0759: static public class Navigator extends JavaScriptEngine {
0760:
0761: private ClientProperties _clientProperties;
0762:
0763: public String getClassName() {
0764: return "Navigator";
0765: }
0766:
0767: void setClientProperties(ClientProperties clientProperties) {
0768: _clientProperties = clientProperties;
0769: }
0770:
0771: public String jsGet_appName() {
0772: return _clientProperties.getApplicationName();
0773: }
0774:
0775: public String jsGet_appCodeName() {
0776: return _clientProperties.getApplicationCodeName();
0777: }
0778:
0779: public String jsGet_appVersion() {
0780: return _clientProperties.getApplicationVersion();
0781: }
0782:
0783: public String jsGet_userAgent() {
0784: return _clientProperties.getUserAgent();
0785: }
0786:
0787: public String jsGet_platform() {
0788: return _clientProperties.getPlatform();
0789: }
0790:
0791: public Object[] jsGet_plugins() {
0792: return new Object[0];
0793: }
0794:
0795: public boolean jsFunction_javaEnabled() {
0796: return false; // no support is provided for applets at present
0797: }
0798:
0799: }
0800:
0801: static public class Screen extends JavaScriptEngine {
0802:
0803: private ClientProperties _clientProperties;
0804:
0805: void setClientProperties(ClientProperties clientProperties) {
0806: _clientProperties = clientProperties;
0807: }
0808:
0809: public String getClassName() {
0810: return "Screen";
0811: }
0812:
0813: public int jsGet_availWidth() {
0814: return _clientProperties.getAvailableScreenWidth();
0815: }
0816:
0817: public int jsGet_availHeight() {
0818: return _clientProperties.getAvailHeight();
0819: }
0820:
0821: }
0822:
0823: static public class ElementArray extends ScriptableObject {
0824:
0825: private JavaScriptEngine _contents[] = new HTMLElement[0];
0826:
0827: static ElementArray newElementArray(Scriptable parent) {
0828: try {
0829: return (ElementArray) Context.getCurrentContext()
0830: .newObject(parent, "ElementArray");
0831: } catch (PropertyException e) {
0832: throw new RhinoException(e);
0833: } catch (NotAFunctionException e) {
0834: throw new RhinoException(e);
0835: } catch (JavaScriptException e) {
0836: throw new RhinoException(e);
0837: }
0838: }
0839:
0840: public ElementArray() {
0841: }
0842:
0843: void initialize(JavaScriptEngine[] contents) {
0844: _contents = contents;
0845: }
0846:
0847: public int jsGet_length() {
0848: return _contents.length;
0849: }
0850:
0851: public String getClassName() {
0852: return "ElementArray";
0853: }
0854:
0855: public Object get(int i, Scriptable scriptable) {
0856: if (i >= 0 && i < _contents.length) {
0857: return _contents[i];
0858: } else {
0859: return super .get(i, scriptable);
0860: }
0861: }
0862:
0863: public Object get(String name, Scriptable scriptable) {
0864: for (int i = 0; i < _contents.length; i++) {
0865: JavaScriptEngine content = _contents[i];
0866: if (name.equalsIgnoreCase(content.getID()))
0867: return content;
0868: }
0869: for (int i = 0; i < _contents.length; i++) {
0870: JavaScriptEngine content = _contents[i];
0871: if (name.equalsIgnoreCase(content.getName()))
0872: return content;
0873: }
0874: return super .get(name, scriptable);
0875: }
0876:
0877: protected JavaScriptEngine[] getContents() {
0878: return _contents;
0879: }
0880: }
0881:
0882: static public class HTMLElement extends JavaScriptEngine {
0883:
0884: private Style _style;
0885: private Document _document;
0886:
0887: public String getClassName() {
0888: return "HTMLElement";
0889: }
0890:
0891: public Document jsGet_document() {
0892: return _document;
0893: }
0894:
0895: public Style jsGet_style() {
0896: return _style;
0897: }
0898:
0899: void initialize(JavaScriptEngine parent,
0900: ScriptableDelegate scriptable)
0901: throws JavaScriptException, NotAFunctionException,
0902: PropertyException, SAXException {
0903: super .initialize(parent, scriptable);
0904: _document = (Document) parent;
0905: _style = (Style) Context.getCurrentContext().newObject(
0906: this , "Style");
0907: }
0908:
0909: }
0910:
0911: static public class Image extends HTMLElement {
0912:
0913: public String getClassName() {
0914: return "Image";
0915: }
0916: }
0917:
0918: static public class Link extends HTMLElement {
0919:
0920: public Document jsGet_document() {
0921: return super .jsGet_document();
0922: }
0923:
0924: public String getClassName() {
0925: return "Link";
0926: }
0927: }
0928:
0929: static public class Form extends HTMLElement {
0930:
0931: private ElementArray _controls;
0932:
0933: public String getClassName() {
0934: return "Form";
0935: }
0936:
0937: public String jsGet_action() {
0938: return getDelegate().getAction();
0939: }
0940:
0941: public void jsSet_action(String action) {
0942: getDelegate().setAction(action);
0943: }
0944:
0945: public Scriptable jsGet_elements() throws PropertyException,
0946: NotAFunctionException, JavaScriptException {
0947: if (_controls == null) {
0948: initializeControls();
0949: }
0950: return _controls;
0951: }
0952:
0953: public Object jsFunction_getElementsByTagName(String name)
0954: throws SAXException {
0955: return toElementArray(getDelegate().getElementsByTagName(
0956: name));
0957: }
0958:
0959: public void jsFunction_submit() throws IOException,
0960: SAXException {
0961: getDelegate().submit();
0962: }
0963:
0964: public void jsFunction_reset() throws IOException, SAXException {
0965: getDelegate().reset();
0966: }
0967:
0968: private void initializeControls() throws PropertyException,
0969: NotAFunctionException, JavaScriptException {
0970: ScriptableDelegate scriptables[] = getDelegate()
0971: .getElementDelegates();
0972: Control[] controls = new Control[scriptables.length];
0973: for (int i = 0; i < controls.length; i++) {
0974: controls[i] = (Control) toScriptable(scriptables[i]);
0975: }
0976: _controls = (ElementArray) Context.getCurrentContext()
0977: .newObject(this , "ElementArray");
0978: _controls.initialize(controls);
0979: }
0980:
0981: private WebForm.Scriptable getDelegate() {
0982: return (WebForm.Scriptable) _scriptable;
0983: }
0984:
0985: }
0986:
0987: static public class Control extends JavaScriptEngine {
0988:
0989: private Form _form;
0990:
0991: public String getClassName() {
0992: return "Control";
0993: }
0994:
0995: public Form jsGet_form() {
0996: return _form;
0997: }
0998:
0999: public void jsFunction_focus() {
1000: }
1001:
1002: public void jsFunction_select() {
1003: }
1004:
1005: public void jsFunction_click() throws IOException, SAXException {
1006: getDelegate().click();
1007: }
1008:
1009: private Input getDelegate() {
1010: return (Input) _scriptable;
1011: }
1012:
1013: void initialize(JavaScriptEngine parent,
1014: ScriptableDelegate scriptable)
1015: throws JavaScriptException, NotAFunctionException,
1016: PropertyException, SAXException {
1017: super .initialize(parent, scriptable);
1018: if (parent instanceof Form)
1019: _form = (Form) parent;
1020: }
1021:
1022: }
1023:
1024: static public class Options extends JavaScriptEngine {
1025:
1026: public String getClassName() {
1027: return "Options";
1028: }
1029:
1030: public int jsGet_length() {
1031: return getDelegate().getLength();
1032: }
1033:
1034: public void jsSet_length(int length) {
1035: getDelegate().setLength(length);
1036: }
1037:
1038: public void put(int i, Scriptable scriptable, Object object) {
1039: if (object == null) {
1040: getDelegate().put(i, null);
1041: } else {
1042: if (!(object instanceof Option))
1043: throw new IllegalArgumentException(
1044: "May only add an Option to this array");
1045: Option option = (Option) object;
1046: getDelegate().put(i, option.getDelegate());
1047: }
1048: }
1049:
1050: private SelectionOptions getDelegate() {
1051: return (SelectionOptions) _scriptable;
1052: }
1053:
1054: }
1055:
1056: static public class Option extends JavaScriptEngine {
1057:
1058: public String getClassName() {
1059: return "Option";
1060: }
1061:
1062: public void jsConstructor(String text, String value,
1063: boolean defaultSelected, boolean selected) {
1064: _scriptable = WebResponse.newDelegate("Option");
1065: getDelegate().initialize(text, value, defaultSelected,
1066: selected);
1067: }
1068:
1069: public int jsGet_index() {
1070: return getDelegate().getIndex();
1071: }
1072:
1073: public String jsGet_text() {
1074: return getDelegate().getText();
1075: }
1076:
1077: public void jsSet_text(String text) {
1078: getDelegate().setText(text);
1079: }
1080:
1081: public String jsGet_value() {
1082: return getDelegate().getValue();
1083: }
1084:
1085: public void jsSet_value(String value) {
1086: getDelegate().setValue(value);
1087: }
1088:
1089: public boolean jsGet_selected() {
1090: return getDelegate().isSelected();
1091: }
1092:
1093: public void jsSet_selected(boolean selected) {
1094: getDelegate().setSelected(selected);
1095: }
1096:
1097: public boolean jsGet_defaultSelected() {
1098: return getDelegate().isDefaultSelected();
1099: }
1100:
1101: SelectionOption getDelegate() {
1102: return (SelectionOption) _scriptable;
1103: }
1104: }
1105:
1106: }
1107:
1108: class RhinoException extends RuntimeException {
1109:
1110: private Exception _cause;
1111:
1112: public RhinoException(Exception cause) {
1113: _cause = cause;
1114: }
1115:
1116: public String getMessage() {
1117: return "Rhino exception: " + _cause;
1118: }
1119: }
|