diff options
Diffstat (limited to 'files/ru/rhino/embedding_tutorial/index.html')
-rw-r--r-- | files/ru/rhino/embedding_tutorial/index.html | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/files/ru/rhino/embedding_tutorial/index.html b/files/ru/rhino/embedding_tutorial/index.html new file mode 100644 index 0000000000..eb56c3050c --- /dev/null +++ b/files/ru/rhino/embedding_tutorial/index.html @@ -0,0 +1,302 @@ +--- +title: 'Руководство: Внедрение кода Rhino' +slug: Rhino/Embedding_tutorial +translation_of: Mozilla/Projects/Rhino/Embedding_tutorial +--- +<p>Внедрение кода Rhino простое но тем не менее приводит к хорошему результату. <span id="result_box" lang="ru"><span>Приложив больше усилии к embedder, исполняемые сценарии могут быть настроены дополнительно.</span></span></p> + +<p><span lang="ru"><span>В этом руководстве по шагово мы рассмотрим способы от простого сценария внедрения кода до сложного. Примеры кода будут соправождать нас в процессе изучения. </span></span></p> + +<p>Примеры можно найти в папках дистрибутива <code>rhino/examples</code> и cvs сервере по адресу <code>mozilla/js/rhino/examples</code>. В этом руководстве мы будем ссылатся на эти примеры посредством <a href="http://lxr.mozilla.org/">lxr</a>.</p> + +<p> JavaScript код будет помечен зеленым, Java код так же будет помечен зеленым<span class="java_js_code">,</span> и shell logs будет отмечен пурпурным.</p> + +<h2 id="Содержание">Содержание:</h2> + +<ul class="toc"> + <li><a href="#runScript">RunScript: A simple embedding</a> + + <ul> + <li><a href="#enteringContext">Entering a Context</a></li> + <li><a href="#initializing">Initializing standard objects</a></li> + <li><a href="#collecting">Collecting the arguments</a></li> + <li><a href="#evaluating">Evaluating a script</a></li> + <li><a href="#print">Printing the result</a></li> + <li><a href="#exit">Exiting the Context</a></li> + </ul> + </li> + <li><a href="#expose">Expose Java APIs</a> + <ul> + <li><a href="#useJava">Using Java APIs</a></li> + <li><a href="#implementingInterfaces">Implementing interfaces</a></li> + <li><a href="#addJava">Adding Java objects</a></li> + </ul> + </li> + <li><a href="#usingJSObjs">Using JavaScript objects from Java</a> + <ul> + <li><a href="#usingJSvars">Using JavaScript variables</a></li> + <li><a href="#callingJSfuns">Calling JavaScript functions</a></li> + </ul> + </li> + <li><a href="#javaScriptHostObjects">JavaScript host objects</a> + <ul> + <li><a href="#definingHostObjects">Defining Host Objects</a></li> + <li><a href="#counter">Counter example</a> + <ul> + <li><a href="#counterCtors">Counter's constructors</a></li> + <li><a href="#classname">Class name</a></li> + <li><a href="#dynamic">Dynamic properties</a></li> + <li><a href="#definingMethods">Defining JavaScript "methods"</a></li> + <li><a href="#addingCounter">Adding Counter to RunScript</a></li> + </ul> + </li> + </ul> + </li> +</ul> + +<h2 id="RunScript_Простой_пример"><a id="runScript" name="runScript">RunScript: Простой пример</a></h2> + +<p>Возможно самый простой пример внедрения Rhino вы найдете здесь <a href="https://dxr.mozilla.org/mozilla/source/js/rhino/examples/RunScript.java">RunScript example</a>. Он считывает строку параметра, который должен быть фрагментом js-кода, запускает код и выводит результат.</p> + +<p>Ниже приведен данный пример. Используйте команду RunScript в командной строке консоли:</p> + +<pre class="code shell_logs_code">$ java RunScript "Math.cos(Math.PI)" +-1 +$ java RunScript "function f(x){return x+1} f(7)" +8 +</pre> + +<p>Примечание: Rhino классы и класс RunScript должны быть прописаны в classpath. Let's step through the body of <code>main</code> one line at time.</p> + +<h3 id="Entering_a_Context"><a id="enteringContext" name="enteringContext">Entering a Context</a></h3> + +<p>The code</p> + +<pre class="code java_js_code">Context cx = Context.enter(); +</pre> + +<p>Creates and enters a <code>Context</code>. A <code>Context</code> stores information about the execution environment of a script.</p> + +<h3 id="Initializing_standard_objects"><a name="initializing">Initializing standard objects</a></h3> + +<p>The code</p> + +<pre class="code java_js_code">Scriptable scope = cx.initStandardObjects(); +</pre> + +<p>Initializes the standard objects (<code>Object</code>, <code>Function</code>, etc.) This must be done before scripts can be executed. The <var>null</var> parameter tells <code>initStandardObjects</code> to create and return a scope object that we use in later calls.</p> + +<h3 id="Collecting_the_arguments"><a id="collecting" name="collecting">Collecting the arguments</a></h3> + +<p>This code is standard Java and not specific to Rhino. It just collects all the arguments and concatenates them together.</p> + +<pre class="code java_js_code">String s = ""; +for (int i=0; i < args.length; i++) { + s += args[i]; +} +</pre> + +<h3 id="Evaluating_a_script"><a id="evaluating" name="evaluating">Evaluating a script</a></h3> + +<p>The code</p> + +<pre class="code java_js_code">Object result = cx.evaluateString(scope, s, "<cmd>", 1, null); +</pre> + +<p>uses the Context <code>cx</code> to evaluate a string. Evaluation of the script looks up variables in <var>scope</var>, and errors will be reported with the filename <code><cmd></code> and line number 1.</p> + +<h3 id="Printing_the_result"><a id="print" name="print">Printing the result</a></h3> + +<p>The code</p> + +<pre class="code java_js_code">System.out.println(cx.toString(result)); +</pre> + +<p>prints the result of evaluating the script (contained in the variable <var>result</var>). <var>result</var> could be a string, JavaScript object, or other values. The <code>toString</code> method converts any JavaScript value to a string.</p> + +<h3 id="Exiting_the_Context"><a id="exit" name="exit">Exiting the Context</a></h3> + +<p>The code</p> + +<pre class="code java_js_code">} finally { + Context.exit(); +} +</pre> + +<p>exits the Context. This removes the association between the Context and the current thread and is an essential cleanup action. There should be a call to <code>exit</code> for every call to <code>enter</code>. To make sure that it is called even if an exception is thrown, it is put into the finally block corresponding to the try block starting after <code>Context.enter()</code>.</p> + +<h2 id="Expose_Java_APIs"><a id="expose" name="expose">Expose Java APIs</a></h2> + +<h3 id="Using_Java_APIs"><a id="useJava" name="useJava">Using Java APIs</a></h3> + +<p>No additional code in the embedding needed! The JavaScript feature called<em>LiveConnect</em> allows JavaScript programs to interact with Java objects:</p> + +<pre class="code shell_logs_code">$ java RunScript "java.lang.System.out.println(3)" +3.0 +undefined +</pre> + +<h3 id="Implementing_interfaces"><a id="implementingInterfaces" name="implementingInterfaces">Implementing interfaces</a></h3> + +<p>Using Rhino, JavaScript objects can implement arbitrary Java interfaces. There's no Java code to write -- it's part of Rhino's LiveConnect implementation. For example, we can see how to implement java.lang.Runnable in a Rhino shell session:</p> + +<pre class="code shell_logs_code">js> obj = { run: function() { print("hi"); } } +[object Object] +js> obj.run() +hi +js> r = new java.lang.Runnable(obj); +[object Object] +js> t = new java.lang.Thread(r) +Thread[Thread-0,5,main] +js> t.start() +hi +</pre> + +<h3 id="Adding_Java_objects"><a id="addJava" name="addJava">Adding Java objects</a></h3> + +<p>The next example is <a href="https://dxr.mozilla.org/mozilla/source/js/rhino/examples/RunScript2.java">RunScript2</a>. This is the same as RunScript, but with the addition of two extra lines of code:</p> + +<pre class="code java_js_code">Object wrappedOut = Context.javaToJS(System.out, scope); +ScriptableObject.putProperty(scope, "out", wrappedOut); +</pre> + +<p>These lines add a global variable <code>out</code> that is a JavaScript reflection of the <code>System.out</code> variable:</p> + +<pre class="code shell_logs_code">$ java RunScript2 "out.println(42)" +42.0 +undefined +</pre> + +<h2 id="Using_JavaScript_objects_from_Java"><a id="usingJSObjs" name="usingJSObjs">Using JavaScript objects from Java</a></h2> + +<p>After evaluating a script it's possible to query the scope for variables and functions, extracting values and calling JavaScript functions. This is illustrated in the <a href="https://dxr.mozilla.org/mozilla/source/js/rhino/examples/RunScript3.java">RunScript3</a> example. This example adds the ability to print the value of variable <var>x</var> and the result of calling function <code>f</code>. Both <var>x</var> and <var>f</var> are expected to be defined by the evaluated script. For example,</p> + +<pre class="code shell_logs_code">$ java RunScript3 "x = 7" +x = 7 +f is undefined or not a function. +$ java RunScript3 "function f(a) { return a; }" +x is not defined. +f("my args") = my arg +</pre> + +<h3 id="Using_JavaScript_variables"><a id="usingJSvars" name="usingJSvars">Using JavaScript variables</a></h3> + +<p>To print out the value of <var>x</var>, we add the following code:</p> + +<pre class="code java_js_code">Object x = scope.get("x", scope); +if (x == Scriptable.NOT_FOUND) { + System.out.println("x is not defined."); +} else { + System.out.println("x = " + Context.toString(x)); +} +</pre> + +<h3 id="Calling_JavaScript_functions"><a id="callingJSfuns" name="callingJSfuns">Calling JavaScript functions</a></h3> + +<p>To get the function <var>f</var>, call it, and print the result, we add this code:</p> + +<pre class="code java_js_code">Object fObj = scope.get("f", scope); +if (!(fObj instanceof Function)) { + System.out.println("f is undefined or not a function."); +} else { + Object functionArgs[] = { "my arg" }; + Function f = (Function)fObj; + Object result = f.call(cx, scope, scope, functionArgs); + String report = "f('my args') = " + Context.toString(result); + System.out.println(report); +} +</pre> + +<h2 id="JavaScript_host_objects"><a id="javaScriptHostObjects" name="javaScriptHostObjects">JavaScript host objects</a></h2> + +<h3 id="Defining_Host_Objects"><a id="definingHostObjects" name="definingHostObjects">Defining Host Objects</a></h3> + +<p>Custom host objects can implement special JavaScript features like dynamic properties.</p> + +<h3 id="Counter_example"><a id="counter" name="counter">Counter example</a></h3> + +<p>The <a href="https://dxr.mozilla.org/mozilla/source/js/rhino/examples/Counter.java">Counter example</a> is a simple host object. We'll go through it method by method below.</p> + +<p>It's easy to try out new host object classes in the shell using its built-in <code>defineClass</code> function. We'll see how to add it to RunScript later. (Note that because the <code>java -jar</code> option preempts the rest of the classpath, we can't use that and access the <code>Counter</code> class.)</p> + +<pre class="code shell_logs_code">$ java -cp "js.jar;examples" org.mozilla.javascript.tools.shell.Main +js> defineClass("Counter") +js> c = new Counter(7) +[object Counter] +js> c.count +7 +js> c.count +8 +js> c.count +9 +js> c.resetCount() +js> c.count +0 +</pre> + +<h3 id="Counter's_constructors"><a id="counterCtors" name="counterCtors">Counter's constructors</a></h3> + +<p>The zero-argument constructor is used by Rhino runtime to create instances. For the counter example, no initialization work is needed, so the implementation is empty.</p> + +<pre class="code java_js_code">public Counter () { } +</pre> + +<p>The method <code>jsConstructor</code> defines the JavaScript constructor that was called with the expression <code>new Counter(7)</code> in the JavaScript code above.</p> + +<pre class="code java_js_code">public void jsConstructor(int a) { count += a; } +</pre> + +<h3 id="Class_name"><a id="classname" name="classname">Class name</a></h3> + +<p>The class name is defined by the <code>getClassName</code> method. This is used to determine the name of the constructor.</p> + +<pre class="code java_js_code">public String getClassName() { return "Counter"; +} +</pre> + +<h3 id="Dynamic_properties"><a id="dynamic" name="dynamic">Dynamic properties</a></h3> + +<p>Dynamic properties are defined by methods beginning with <code>jsGet_</code> or <code>jsSet_</code>. The method <code>jsGet_count</code> defines the<em>count</em> property.</p> + +<pre class="code java_js_code">public int jsGet_count() { return count++; +} +</pre> + +<p>The expression <code>c.count</code> in the JavaScript code above results in a call to this method.</p> + +<h3 id="Defining_JavaScript_methods"><a id="definingMethods" name="definingMethods">Defining JavaScript "methods"</a></h3> + +<p>Methods can be defined using the <code>jsFunction_ prefix</code>. Here we define <code>resetCount</code> for JavaScript.</p> + +<pre class="code java_js_code">public void jsFunction_resetCount() { count += 0; } +</pre> + +<p>The call <code>c.resetCount()</code> above calls this method.</p> + +<h3 id="Adding_Counter_to_RunScript"><a id="addingCounter" name="addingCounter">Adding Counter to RunScript</a></h3> + +<p>Now take a look at the <a href="https://dxr.mozilla.org/mozilla/source/js/rhino/examples/RunScript4.java">RunScript4 example</a>. It's the same as RunScript except for two additions. The method <code>ScriptableObject.defineClass</code> uses a Java class to define the Counter "class" in the top-level scope:</p> + +<pre class="code java_js_code">ScriptableObject.defineClass(scope, Counter.class); +</pre> + +<p>Now we can reference the <code>Counter</code> object from our script:</p> + +<pre class="code shell_logs_code">$ java RunScript4 "c = new Counter(3); c.count; +c.count;" +</pre> + +<p>It also creates a new instance of the <code>Counter</code> object from within our Java code, constructing it with the value 7, and assigning it to the top-level variable <code>myCounter</code>:</p> + +<pre class="code java_js_code">Object[] arg = { new Integer(7) }; +Scriptable myCounter = cx.newObject(scope, "Counter", arg); +scope.put("myCounter", scope, myCounter); +</pre> + +<p>Now we can reference the <code>myCounter</code> object from our script:</p> + +<pre class="code shell_logs_code">$ java RunScript3 'RunScript4 'myCounter.count; myCounter.count' +8 +</pre> |