RhinoScriptEngine.kt 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /*
  2. * Copyright (c) 2005, 2011, 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. package com.script.rhino
  26. import com.script.*
  27. import org.mozilla.javascript.*
  28. import org.mozilla.javascript.Function
  29. import java.io.IOException
  30. import java.io.Reader
  31. import java.io.StringReader
  32. import java.lang.reflect.Method
  33. import java.security.*
  34. /**
  35. * Implementation of `ScriptEngine` using the Mozilla Rhino
  36. * interpreter.
  37. *
  38. * @author Mike Grogan
  39. * @author A. Sundararajan
  40. * @since 1.6
  41. */
  42. @Suppress("MemberVisibilityCanBePrivate")
  43. class RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
  44. var accessContext: AccessControlContext? = null
  45. private var topLevel: RhinoTopLevel? = null
  46. private val indexedProps: MutableMap<Any, Any?>
  47. private val implementor: InterfaceImplementor
  48. fun run(function: (Context) -> Any?): Any? {
  49. return try {
  50. val context = Context.enter()
  51. function.invoke(context)
  52. } finally {
  53. Context.exit()
  54. }
  55. }
  56. @Throws(ScriptException::class)
  57. override fun eval(reader: Reader, scope: Scriptable): Any? {
  58. val cx = Context.enter()
  59. val ret: Any?
  60. try {
  61. var filename = this["javax.script.filename"] as? String
  62. filename = filename ?: "<Unknown source>"
  63. ret = cx.evaluateReader(scope, reader, filename, 1, null)
  64. } catch (re: RhinoException) {
  65. val line = if (re.lineNumber() == 0) -1 else re.lineNumber()
  66. val msg: String = if (re is JavaScriptException) {
  67. re.value.toString()
  68. } else {
  69. re.toString()
  70. }
  71. val se = ScriptException(msg, re.sourceName(), line)
  72. se.initCause(re)
  73. throw se
  74. } catch (var14: IOException) {
  75. throw ScriptException(var14)
  76. } finally {
  77. Context.exit()
  78. }
  79. return unwrapReturnValue(ret)
  80. }
  81. override fun createBindings(): Bindings {
  82. return SimpleBindings()
  83. }
  84. @Throws(ScriptException::class, NoSuchMethodException::class)
  85. override fun invokeFunction(name: String, vararg args: Any): Any? {
  86. return this.invoke(null, name, *args)
  87. }
  88. @Throws(ScriptException::class, NoSuchMethodException::class)
  89. override fun invokeMethod(obj: Any?, name: String, vararg args: Any): Any? {
  90. return if (obj == null) {
  91. throw IllegalArgumentException("脚本对象不能为空")
  92. } else {
  93. this.invoke(obj, name, *args)
  94. }
  95. }
  96. @Suppress("UNCHECKED_CAST")
  97. @Throws(ScriptException::class, NoSuchMethodException::class)
  98. private operator fun invoke(thiz: Any?, name: String?, vararg args: Any?): Any? {
  99. var thiz1 = thiz
  100. val cx = Context.enter()
  101. val var11: Any?
  102. try {
  103. if (name == null) {
  104. throw NullPointerException("方法名为空")
  105. }
  106. if (thiz1 != null && thiz1 !is Scriptable) {
  107. thiz1 = Context.toObject(thiz1, topLevel)
  108. }
  109. val engineScope = getRuntimeScope(context)
  110. val localScope = if (thiz1 != null) thiz1 as Scriptable else engineScope
  111. val obj = ScriptableObject.getProperty(localScope, name) as? Function
  112. ?: throw NoSuchMethodException("no such method: $name")
  113. var scope = obj.parentScope
  114. if (scope == null) {
  115. scope = engineScope
  116. }
  117. val result = obj.call(cx, scope, localScope, wrapArguments(args as? Array<Any?>))
  118. var11 = unwrapReturnValue(result)
  119. } catch (re: RhinoException) {
  120. val line = if (re.lineNumber() == 0) -1 else re.lineNumber()
  121. val se = ScriptException(re.toString(), re.sourceName(), line)
  122. se.initCause(re)
  123. throw se
  124. } finally {
  125. Context.exit()
  126. }
  127. return var11
  128. }
  129. override fun <T> getInterface(clazz: Class<T>): T? {
  130. return try {
  131. implementor.getInterface(null, clazz)
  132. } catch (var3: ScriptException) {
  133. null
  134. }
  135. }
  136. override fun <T> getInterface(obj: Any?, paramClass: Class<T>): T? {
  137. return if (obj == null) {
  138. throw IllegalArgumentException("脚本对象不能为空")
  139. } else {
  140. try {
  141. implementor.getInterface(obj, paramClass)
  142. } catch (var4: ScriptException) {
  143. null
  144. }
  145. }
  146. }
  147. override fun getRuntimeScope(context: ScriptContext): Scriptable {
  148. val newScope: Scriptable = ExternalScriptable(context, indexedProps)
  149. newScope.prototype = topLevel
  150. newScope.put("context", newScope, context)
  151. return newScope
  152. }
  153. @Throws(ScriptException::class)
  154. override fun compile(script: String): CompiledScript {
  155. return this.compile(StringReader(script) as Reader)
  156. }
  157. @Throws(ScriptException::class)
  158. override fun compile(script: Reader): CompiledScript {
  159. val cx = Context.enter()
  160. val ret: RhinoCompiledScript
  161. try {
  162. var fileName = this["javax.script.filename"] as? String
  163. if (fileName == null) {
  164. fileName = "<Unknown Source>"
  165. }
  166. val scr = cx.compileReader(script, fileName, 1, null)
  167. ret = RhinoCompiledScript(this, scr)
  168. } catch (var9: Exception) {
  169. throw ScriptException(var9)
  170. } finally {
  171. Context.exit()
  172. }
  173. return ret
  174. }
  175. fun wrapArguments(args: Array<Any?>?): Array<Any?> {
  176. return if (args == null) {
  177. Context.emptyArgs
  178. } else {
  179. val res = arrayOfNulls<Any>(args.size)
  180. for (i in res.indices) {
  181. res[i] = Context.javaToJS(args[i], topLevel)
  182. }
  183. res
  184. }
  185. }
  186. fun unwrapReturnValue(result: Any?): Any? {
  187. var result1 = result
  188. if (result1 is Wrapper) {
  189. result1 = result1.unwrap()
  190. }
  191. return if (result1 is Undefined) null else result1
  192. }
  193. init {
  194. if (System.getSecurityManager() != null) {
  195. try {
  196. AccessController.checkPermission(AllPermission())
  197. } catch (var6: AccessControlException) {
  198. accessContext = AccessController.getContext()
  199. }
  200. }
  201. val cx = Context.enter()
  202. try {
  203. topLevel = RhinoTopLevel(cx, this)
  204. } finally {
  205. Context.exit()
  206. }
  207. indexedProps = HashMap()
  208. implementor = object : InterfaceImplementor(this) {
  209. override fun isImplemented(obj: Any?, clazz: Class<*>): Boolean {
  210. var obj1 = obj
  211. return try {
  212. if (obj1 != null && obj1 !is Scriptable) {
  213. obj1 = Context.toObject(obj1, topLevel)
  214. }
  215. val engineScope = getRuntimeScope(context)
  216. val localScope = if (obj1 != null) obj1 as Scriptable else engineScope
  217. val methods = clazz.methods
  218. val methodsSize = methods.size
  219. for (index in 0 until methodsSize) {
  220. val method = methods[index]
  221. if (method.declaringClass != Any::class.java) {
  222. if (ScriptableObject.getProperty(
  223. localScope,
  224. method.name
  225. ) !is Function
  226. ) {
  227. return false
  228. }
  229. }
  230. }
  231. true
  232. } finally {
  233. Context.exit()
  234. }
  235. }
  236. override fun convertResult(method: Method?, res: Any?): Any? {
  237. method ?: return null
  238. val desiredType = method.returnType
  239. if (desiredType == Void.TYPE) return null
  240. return Context.jsToJava(res, desiredType)
  241. }
  242. }
  243. }
  244. @Suppress("unused")
  245. companion object {
  246. init {
  247. ContextFactory.initGlobal(object : ContextFactory() {
  248. override fun makeContext(): Context {
  249. val cx = super.makeContext()
  250. cx.languageVersion = 200
  251. cx.optimizationLevel = -1
  252. cx.setClassShutter(RhinoClassShutter)
  253. cx.wrapFactory = RhinoWrapFactory
  254. return cx
  255. }
  256. override fun hasFeature(cx: Context, featureIndex: Int): Boolean {
  257. return when (featureIndex) {
  258. Context.FEATURE_ENABLE_JAVA_MAP_ACCESS -> true
  259. else -> super.hasFeature(cx, featureIndex)
  260. }
  261. }
  262. override fun doTopCall(
  263. callable: Callable,
  264. cx: Context,
  265. scope: Scriptable,
  266. thisObj: Scriptable,
  267. args: Array<Any>
  268. ): Any? {
  269. var accContext: AccessControlContext? = null
  270. val global = ScriptableObject.getTopLevelScope(scope)
  271. val globalProto = global.prototype
  272. if (globalProto is RhinoTopLevel) {
  273. accContext = globalProto.accessContext
  274. }
  275. return if (accContext != null) AccessController.doPrivileged(
  276. PrivilegedAction {
  277. superDoTopCall(callable, cx, scope, thisObj, args)
  278. }, accContext
  279. ) else superDoTopCall(
  280. callable,
  281. cx,
  282. scope,
  283. thisObj,
  284. args
  285. )
  286. }
  287. private fun superDoTopCall(
  288. callable: Callable,
  289. cx: Context,
  290. scope: Scriptable,
  291. thisObj: Scriptable,
  292. args: Array<Any>
  293. ): Any? {
  294. return super.doTopCall(callable, cx, scope, thisObj, args)
  295. }
  296. })
  297. }
  298. }
  299. }