1 /*
   2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /**
  27  * This script contains non-standard, Mozilla compatibility functionality on
  28  * the standard global objects. Please note that it is incomplete. Only the most
  29  * often used functionality is supported.
  30  */
  31 
  32 // JavaAdapter
  33 Object.defineProperty(this, "JavaAdapter", {
  34     configurable: true, enumerable: false, writable: true,
  35     value: function() {
  36         if (arguments.length < 2) {
  37             throw new TypeError("JavaAdapter requires atleast two arguments");
  38         }
  39 
  40         var types = Array.prototype.slice.call(arguments, 0, arguments.length - 1);
  41         var NewType = Java.extend.apply(Java, types);
  42         return new NewType(arguments[arguments.length - 1]);
  43     }
  44 });
  45 
  46 
  47 // importPackage
  48 // avoid unnecessary chaining of __noSuchProperty__ again
  49 // in case user loads this script more than once.
  50 if (typeof importPackage == 'undefined' || !(importPackage instanceof Function)) {
  51 
  52 Object.defineProperty(this, "importPackage", {
  53     configurable: true, enumerable: false, writable: true,
  54     value: (function() {
  55         var _packages = [];
  56         var global = this;
  57         var oldNoSuchProperty = global.__noSuchProperty__;
  58         var __noSuchProperty__ = function(name) {
  59             'use strict';
  60             for (var i in _packages) {
  61                 try {
  62                     var type = Java.type(_packages[i] + "." + name);
  63                     global[name] = type;
  64                     return type;
  65                 } catch (e) {}
  66             }
  67 
  68             if (oldNoSuchProperty) {
  69                 return oldNoSuchProperty.call(this, name);
  70             } else {
  71                 if (this === undefined) {
  72                     throw new ReferenceError(name + " is not defined");
  73                 } else {
  74                     return undefined;
  75                 }
  76             }
  77         }
  78 
  79         Object.defineProperty(global, "__noSuchProperty__", {
  80             writable: true, configurable: true, enumerable: false,
  81             value: __noSuchProperty__
  82         });
  83 
  84         var prefix = "[JavaPackage ";
  85         return function() {
  86             for (var i in arguments) {
  87                 var pkgName = arguments[i];
  88                 if ((typeof pkgName) != 'string') {
  89                     pkgName = String(pkgName);
  90                     // extract name from JavaPackage object
  91                     if (pkgName.startsWith(prefix)) {
  92                         pkgName = pkgName.substring(prefix.length, pkgName.length - 1);
  93                     }
  94                 }
  95                 _packages.push(pkgName);
  96             }
  97         }
  98     })()
  99 });
 100 
 101 }
 102 
 103 // sync
 104 Object.defineProperty(this, "sync", {
 105     configurable: true, enumerable: false, writable: true,
 106     value: function(func, syncobj) {
 107         if (arguments.length < 1 || arguments.length > 2 ) {
 108             throw "sync(function [,object]) parameter count mismatch";
 109         }
 110         return Java.synchronized(func, syncobj);
 111     }
 112 });
 113 
 114 // Object.prototype.__defineGetter__
 115 Object.defineProperty(Object.prototype, "__defineGetter__", {
 116     configurable: true, enumerable: false, writable: true,
 117     value: function(name, func) {
 118         Object.defineProperty(this, name, {
 119             configurable: true, enumerable: true, get: func });
 120     }
 121 });
 122 
 123 // Object.prototype.__defineSetter__
 124 Object.defineProperty(Object.prototype, "__defineSetter__", {
 125     configurable: true, enumerable: false, writable: true,
 126     value: function(name, func) {
 127         Object.defineProperty(this, name, {
 128             configurable: true, enumerable: true, set: func });
 129     }
 130 });
 131 
 132 // Object.prototype.__lookupGetter__
 133 Object.defineProperty(Object.prototype, "__lookupGetter__", {
 134     configurable: true, enumerable: false, writable: true,
 135     value: function(name) {
 136         var obj = this;
 137         while (obj) {
 138             var desc = Object.getOwnPropertyDescriptor(obj, name);
 139             if (desc) return desc.get;
 140             obj = Object.getPrototypeOf(obj);
 141         }
 142         return undefined;
 143     }
 144 });
 145 
 146 // Object.prototype.__lookupSetter__
 147 Object.defineProperty(Object.prototype, "__lookupSetter__", {
 148     configurable: true, enumerable: false, writable: true,
 149     value: function(name) {
 150         var obj = this;
 151         while (obj) {
 152             var desc = Object.getOwnPropertyDescriptor(obj, name);
 153             if (desc) return desc.set;
 154             obj = Object.getPrototypeOf(obj);
 155         }
 156         return undefined;
 157     }
 158 });
 159 
 160 // Object.prototype.toSource
 161 Object.defineProperty(Object.prototype, "toSource", {
 162     configurable: true, enumerable: false, writable: true,
 163     value: function(state) {
 164         if (! state) {
 165             state = java.util.Collections.newSetFromMap(new java.util.HashMap());
 166         }
 167         if (state.contains(this)) {
 168             return "{}";
 169         }
 170         state.add(this);
 171         var str = new java.lang.StringBuffer('({');
 172         for (i in this) {
 173             str.append(i);
 174             str.append(':');
 175             if (this[i] instanceof Object && typeof(this[i].toSource) == 'function') {
 176                 str.append(this[i].toSource(state));
 177             } else {
 178                 str.append(String(this[i]));
 179             }
 180             str.append(', ');
 181         }
 182         // delete last extra command and space
 183         str = str.deleteCharAt(str.length() - 1);
 184         str = str.deleteCharAt(str.length() - 1);
 185         str.append('})');
 186         return str.toString();
 187     }
 188 });
 189 
 190 // Boolean.prototype.toSource
 191 Object.defineProperty(Boolean.prototype, "toSource", {
 192     configurable: true, enumerable: false, writable: true,
 193     value: function() {
 194         return '(new Boolean(' + this.toString() + '))';
 195     }
 196 });
 197 
 198 // Date.prototype.toSource
 199 Object.defineProperty(Date.prototype, "toSource", {
 200     configurable: true, enumerable: false, writable: true,
 201     value: function() {
 202         return '(new Date(' + this.valueOf() + '))';
 203     }
 204 });
 205 
 206 // Function.prototype.toSource -- already implemented in nashorn
 207 
 208 // Number.prototype.toSource
 209 Object.defineProperty(Number.prototype, "toSource", {
 210     configurable: true, enumerable: false, writable: true,
 211     value: function() {
 212         return '(new Number(' + this.toString() + '))';
 213     }
 214 });
 215 
 216 // RegExp.prototype.toSource
 217 Object.defineProperty(RegExp.prototype, "toSource", {
 218     configurable: true, enumerable: false, writable: true,
 219     value: function() {
 220         return this.toString();
 221     }
 222 });
 223 
 224 // String.prototype.toSource
 225 Object.defineProperty(String.prototype, "toSource", {
 226     configurable: true, enumerable: false, writable: true,
 227     value: function() {
 228         return '(new String(' + this.quote() + '))';
 229     }
 230 });
 231 
 232 // Error.prototype.toSource
 233 Object.defineProperty(Error.prototype, "toSource", {
 234     configurable: true, enumerable: false, writable: true,
 235     value: function() {
 236         var msg = this.message? String(this.message).quote() : "''";
 237         return '(new ' + this.name + '(' + msg + '))';
 238     }
 239 });
 240 
 241 // Function.prototype.arity
 242 Object.defineProperty(Function.prototype, "arity", {
 243     configurable: true, enumerable: false,
 244     get: function() { return this.length; },
 245     set: function(x) {
 246         throw new TypeError("Function arity can not be modified");
 247     }
 248 });
 249 
 250 // String.prototype.quote
 251 Object.defineProperty(String.prototype, "quote", {
 252     configurable: true, enumerable: false, writable: true,
 253     value: function() {
 254         return JSON.stringify(this);
 255     }
 256 });
 257 
 258 // HTML generation methods of String.prototype
 259 
 260 // String.prototype.anchor
 261 Object.defineProperty(String.prototype, "anchor", {
 262     configurable: true, enumerable: false, writable: true,
 263     value: function(name) {
 264         return '<a name="' + name + '">' + this + '</a>';
 265     }
 266 });
 267 
 268 // String.prototype.big
 269 Object.defineProperty(String.prototype, "big", {
 270     configurable: true, enumerable: false, writable: true,
 271     value: function() {
 272         return '<big>' + this + '</big>';
 273     }
 274 });
 275 
 276 // String.prototype.blink
 277 Object.defineProperty(String.prototype, "blink", {
 278     configurable: true, enumerable: false, writable: true,
 279     value: function() {
 280         return '<blink>' + this + '</blink>';
 281     }
 282 });
 283 
 284 // String.prototype.bold
 285 Object.defineProperty(String.prototype, "bold", {
 286     configurable: true, enumerable: false, writable: true,
 287     value: function() {
 288         return '<b>' + this + '</b>';
 289     }
 290 });
 291 
 292 // String.prototype.fixed
 293 Object.defineProperty(String.prototype, "fixed", {
 294     configurable: true, enumerable: false, writable: true,
 295     value: function() {
 296         return '<tt>' + this + '</tt>';
 297     }
 298 });
 299 
 300 // String.prototype.fontcolor
 301 Object.defineProperty(String.prototype, "fontcolor", {
 302     configurable: true, enumerable: false, writable: true,
 303     value: function(clr) {
 304         return '<font color="' + clr + '">' + this + '</font>';
 305     }
 306 });
 307 
 308 // String.prototype.fontsize
 309 Object.defineProperty(String.prototype, "fontsize", {
 310     configurable: true, enumerable: false, writable: true,
 311     value: function(size) {
 312         return '<font size="' + size + '">' + this + '</font>';
 313     }
 314 });
 315 
 316 // String.prototype.italics
 317 Object.defineProperty(String.prototype, "italics", {
 318     configurable: true, enumerable: false, writable: true,
 319     value: function() {
 320         return '<i>' + this + '</i>';
 321     }
 322 });
 323 
 324 // String.prototype.link
 325 Object.defineProperty(String.prototype, "link", {
 326     configurable: true, enumerable: false, writable: true,
 327     value: function(url) {
 328         return '<a href="' + url + '">' + this + '</a>';
 329     }
 330 });
 331 
 332 // String.prototype.small
 333 Object.defineProperty(String.prototype, "small", {
 334     configurable: true, enumerable: false, writable: true,
 335     value: function() {
 336         return '<small>' + this + '</small>';
 337     }
 338 });
 339 
 340 // String.prototype.strike
 341 Object.defineProperty(String.prototype, "strike", {
 342     configurable: true, enumerable: false, writable: true,
 343     value: function() {
 344         return '<strike>' + this + '</strike>';
 345     }
 346 });
 347 
 348 // String.prototype.sub
 349 Object.defineProperty(String.prototype, "sub", {
 350     configurable: true, enumerable: false, writable: true,
 351     value: function() {
 352         return '<sub>' + this + '</sub>';
 353     }
 354 });
 355 
 356 // String.prototype.sup
 357 Object.defineProperty(String.prototype, "sup", {
 358     configurable: true, enumerable: false, writable: true,
 359     value: function() {
 360         return '<sup>' + this + '</sup>';
 361     }
 362 });
 363 
 364 // Rhino: global.importClass
 365 Object.defineProperty(this, "importClass", {
 366     configurable: true, enumerable: false, writable: true,
 367     value: function() {
 368         for (var arg in arguments) {
 369             var clazz = arguments[arg];
 370             if (Java.isType(clazz)) {
 371                 var className = Java.typeName(clazz);
 372                 var simpleName = className.substring(className.lastIndexOf('.') + 1);
 373                 this[simpleName] = clazz;
 374             } else {
 375                 throw new TypeError(clazz + " is not a Java class");
 376             }
 377         }
 378     }
 379 });