History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/com/sun/tools/script/shell (4 of 18352 files). Show all

Unified · Split

4 files
  1. java/pkg/com/sun/tools/script/shell/Main.java +587 −0
  2. java/pkg/com/sun/tools/script/shell/init.js +884 −0
  3. java/pkg/com/sun/tools/script/shell/messages.properties +66 −0
  4. java/pkg/com/sun/tools/script/shell/mkfile +8 −0
java/pkg/com/sun/tools/script/shell/Main.java+587−0
@@ -0,0 +1,587 @@
1+/*
2+ * Copyright (c) 2005, 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+package com.sun.tools.script.shell;
27+
28+import java.io.*;
29+import java.net.*;
30+import java.text.*;
31+import java.util.*;
32+import javax.script.*;
33+
34+/**
35+ * This is the main class for Java script shell.
36+ */
37+public class Main {
38+ /**
39+ * main entry point to the command line tool
40+ * @param args command line argument array
41+ */
42+ public static void main(String[] args) {
43+ // parse command line options
44+ String[] scriptArgs = processOptions(args);
45+
46+ // process each script command
47+ for (Command cmd : scripts) {
48+ cmd.run(scriptArgs);
49+ }
50+
51+ System.exit(EXIT_SUCCESS);
52+ }
53+
54+ // Each -e or -f or interactive mode is represented
55+ // by an instance of Command.
56+ private static interface Command {
57+ public void run(String[] arguments);
58+ }
59+
60+ /**
61+ * Parses and processes command line options.
62+ * @param args command line argument array
63+ */
64+ private static String[] processOptions(String[] args) {
65+ // current scripting language selected
66+ String currentLanguage = DEFAULT_LANGUAGE;
67+ // current script file encoding selected
68+ String currentEncoding = null;
69+
70+ // check for -classpath or -cp first
71+ checkClassPath(args);
72+
73+ // have we seen -e or -f ?
74+ boolean seenScript = false;
75+ // have we seen -f - already?
76+ boolean seenStdin = false;
77+ for (int i=0; i < args.length; i++) {
78+ String arg = args[i];
79+ if (arg.equals("-classpath") ||
80+ arg.equals("-cp")) {
81+ // handled already, just continue
82+ i++;
83+ continue;
84+ }
85+
86+ // collect non-option arguments and pass these as script arguments
87+ if (!arg.startsWith("-")) {
88+ int numScriptArgs;
89+ int startScriptArg;
90+ if (seenScript) {
91+ // if we have seen -e or -f already all non-option arguments
92+ // are passed as script arguments
93+ numScriptArgs = args.length - i;
94+ startScriptArg = i;
95+ } else {
96+ // if we have not seen -e or -f, first non-option argument
97+ // is treated as script file name and rest of the non-option
98+ // arguments are passed to script as script arguments
99+ numScriptArgs = args.length - i - 1;
100+ startScriptArg = i + 1;
101+ ScriptEngine se = getScriptEngine(currentLanguage);
102+ addFileSource(se, args[i], currentEncoding);
103+ }
104+ // collect script arguments and return to main
105+ String[] result = new String[numScriptArgs];
106+ System.arraycopy(args, startScriptArg, result, 0, numScriptArgs);
107+ return result;
108+ }
109+
110+ if (arg.startsWith("-D")) {
111+ String value = arg.substring(2);
112+ int eq = value.indexOf('=');
113+ if (eq != -1) {
114+ System.setProperty(value.substring(0, eq),
115+ value.substring(eq + 1));
116+ } else {
117+ if (!value.equals("")) {
118+ System.setProperty(value, "");
119+ } else {
120+ // do not allow empty property name
121+ usage(EXIT_CMD_NO_PROPNAME);
122+ }
123+ }
124+ continue;
125+ } else if (arg.equals("-?") || arg.equals("-help")) {
126+ usage(EXIT_SUCCESS);
127+ } else if (arg.equals("-e")) {
128+ seenScript = true;
129+ if (++i == args.length)
130+ usage(EXIT_CMD_NO_SCRIPT);
131+
132+ ScriptEngine se = getScriptEngine(currentLanguage);
133+ addStringSource(se, args[i]);
134+ continue;
135+ } else if (arg.equals("-encoding")) {
136+ if (++i == args.length)
137+ usage(EXIT_CMD_NO_ENCODING);
138+ currentEncoding = args[i];
139+ continue;
140+ } else if (arg.equals("-f")) {
141+ seenScript = true;
142+ if (++i == args.length)
143+ usage(EXIT_CMD_NO_FILE);
144+ ScriptEngine se = getScriptEngine(currentLanguage);
145+ if (args[i].equals("-")) {
146+ if (seenStdin) {
147+ usage(EXIT_MULTIPLE_STDIN);
148+ } else {
149+ seenStdin = true;
150+ }
151+ addInteractiveMode(se);
152+ } else {
153+ addFileSource(se, args[i], currentEncoding);
154+ }
155+ continue;
156+ } else if (arg.equals("-l")) {
157+ if (++i == args.length)
158+ usage(EXIT_CMD_NO_LANG);
159+ currentLanguage = args[i];
160+ continue;
161+ } else if (arg.equals("-q")) {
162+ listScriptEngines();
163+ }
164+ // some unknown option...
165+ usage(EXIT_UNKNOWN_OPTION);
166+ }
167+
168+ if (! seenScript) {
169+ ScriptEngine se = getScriptEngine(currentLanguage);
170+ addInteractiveMode(se);
171+ }
172+ return new String[0];
173+ }
174+
175+ /**
176+ * Adds interactive mode Command
177+ * @param se ScriptEngine to use in interactive mode.
178+ */
179+ private static void addInteractiveMode(final ScriptEngine se) {
180+ scripts.add(new Command() {
181+ public void run(String[] args) {
182+ setScriptArguments(se, args);
183+ processSource(se, "-", null);
184+ }
185+ });
186+ }
187+
188+ /**
189+ * Adds script source file Command
190+ * @param se ScriptEngine used to evaluate the script file
191+ * @param fileName script file name
192+ * @param encoding script file encoding
193+ */
194+ private static void addFileSource(final ScriptEngine se,
195+ final String fileName,
196+ final String encoding) {
197+ scripts.add(new Command() {
198+ public void run(String[] args) {
199+ setScriptArguments(se, args);
200+ processSource(se, fileName, encoding);
201+ }
202+ });
203+ }
204+
205+ /**
206+ * Adds script string source Command
207+ * @param se ScriptEngine to be used to evaluate the script string
208+ * @param source Script source string
209+ */
210+ private static void addStringSource(final ScriptEngine se,
211+ final String source) {
212+ scripts.add(new Command() {
213+ public void run(String[] args) {
214+ setScriptArguments(se, args);
215+ String oldFile = setScriptFilename(se, "<string>");
216+ try {
217+ evaluateString(se, source);
218+ } finally {
219+ setScriptFilename(se, oldFile);
220+ }
221+ }
222+ });
223+ }
224+
225+ /**
226+ * Prints list of script engines available and exits.
227+ */
228+ private static void listScriptEngines() {
229+ List<ScriptEngineFactory> factories = engineManager.getEngineFactories();
230+ for (ScriptEngineFactory factory: factories) {
231+ getError().println(getMessage("engine.info",
232+ new Object[] { factory.getLanguageName(),
233+ factory.getLanguageVersion(),
234+ factory.getEngineName(),
235+ factory.getEngineVersion()
236+ }));
237+ }
238+ System.exit(EXIT_SUCCESS);
239+ }
240+
241+ /**
242+ * Processes a given source file or standard input.
243+ * @param se ScriptEngine to be used to evaluate
244+ * @param filename file name, can be null
245+ * @param encoding script file encoding, can be null
246+ */
247+ private static void processSource(ScriptEngine se, String filename,
248+ String encoding) {
249+ if (filename.equals("-")) {
250+ BufferedReader in = new BufferedReader
251+ (new InputStreamReader(getIn()));
252+ boolean hitEOF = false;
253+ String prompt = getPrompt(se);
254+ se.put(ScriptEngine.FILENAME, "<STDIN>");
255+ while (!hitEOF) {
256+ getError().print(prompt);
257+ String source = "";
258+ try {
259+ source = in.readLine();
260+ } catch (IOException ioe) {
261+ getError().println(ioe.toString());
262+ }
263+ if (source == null) {
264+ hitEOF = true;
265+ break;
266+ }
267+ Object res = evaluateString(se, source, false);
268+ if (res != null) {
269+ res = res.toString();
270+ if (res == null) {
271+ res = "null";
272+ }
273+ getError().println(res);
274+ }
275+ }
276+ } else {
277+ FileInputStream fis = null;
278+ try {
279+ fis = new FileInputStream(filename);
280+ } catch (FileNotFoundException fnfe) {
281+ getError().println(getMessage("file.not.found",
282+ new Object[] { filename }));
283+ System.exit(EXIT_FILE_NOT_FOUND);
284+ }
285+ evaluateStream(se, fis, filename, encoding);
286+ }
287+ }
288+
289+ /**
290+ * Evaluates given script source
291+ * @param se ScriptEngine to evaluate the string
292+ * @param script Script source string
293+ * @param exitOnError whether to exit the process on script error
294+ */
295+ private static Object evaluateString(ScriptEngine se,
296+ String script, boolean exitOnError) {
297+ try {
298+ return se.eval(script);
299+ } catch (ScriptException sexp) {
300+ getError().println(getMessage("string.script.error",
301+ new Object[] { sexp.getMessage() }));
302+ if (exitOnError)
303+ System.exit(EXIT_SCRIPT_ERROR);
304+ } catch (Exception exp) {
305+ exp.printStackTrace(getError());
306+ if (exitOnError)
307+ System.exit(EXIT_SCRIPT_ERROR);
308+ }
309+
310+ return null;
311+ }
312+
313+ /**
314+ * Evaluate script string source and exit on script error
315+ * @param se ScriptEngine to evaluate the string
316+ * @param script Script source string
317+ */
318+ private static void evaluateString(ScriptEngine se, String script) {
319+ evaluateString(se, script, true);
320+ }
321+
322+ /**
323+ * Evaluates script from given reader
324+ * @param se ScriptEngine to evaluate the string
325+ * @param reader Reader from which is script is read
326+ * @param name file name to report in error.
327+ */
328+ private static Object evaluateReader(ScriptEngine se,
329+ Reader reader, String name) {
330+ String oldFilename = setScriptFilename(se, name);
331+ try {
332+ return se.eval(reader);
333+ } catch (ScriptException sexp) {
334+ getError().println(getMessage("file.script.error",
335+ new Object[] { name, sexp.getMessage() }));
336+ System.exit(EXIT_SCRIPT_ERROR);
337+ } catch (Exception exp) {
338+ exp.printStackTrace(getError());
339+ System.exit(EXIT_SCRIPT_ERROR);
340+ } finally {
341+ setScriptFilename(se, oldFilename);
342+ }
343+ return null;
344+ }
345+
346+ /**
347+ * Evaluates given input stream
348+ * @param se ScriptEngine to evaluate the string
349+ * @param is InputStream from which script is read
350+ * @param name file name to report in error
351+ */
352+ private static Object evaluateStream(ScriptEngine se,
353+ InputStream is, String name,
354+ String encoding) {
355+ BufferedReader reader = null;
356+ if (encoding != null) {
357+ try {
358+ reader = new BufferedReader(new InputStreamReader(is,
359+ encoding));
360+ } catch (UnsupportedEncodingException uee) {
361+ getError().println(getMessage("encoding.unsupported",
362+ new Object[] { encoding }));
363+ System.exit(EXIT_NO_ENCODING_FOUND);
364+ }
365+ } else {
366+ reader = new BufferedReader(new InputStreamReader(is));
367+ }
368+ return evaluateReader(se, reader, name);
369+ }
370+
371+ /**
372+ * Prints usage message and exits
373+ * @param exitCode process exit code
374+ */
375+ private static void usage(int exitCode) {
376+ getError().println(getMessage("main.usage",
377+ new Object[] { PROGRAM_NAME }));
378+ System.exit(exitCode);
379+ }
380+
381+ /**
382+ * Gets prompt for interactive mode
383+ * @return prompt string to use
384+ */
385+ private static String getPrompt(ScriptEngine se) {
386+ List<String> names = se.getFactory().getNames();
387+ return names.get(0) + "> ";
388+ }
389+
390+ /**
391+ * Get formatted, localized error message
392+ */
393+ private static String getMessage(String key, Object[] params) {
394+ return MessageFormat.format(msgRes.getString(key), params);
395+ }
396+
397+ // input stream from where we will read
398+ private static InputStream getIn() {
399+ return System.in;
400+ }
401+
402+ // stream to print error messages
403+ private static PrintStream getError() {
404+ return System.err;
405+ }
406+
407+ // get current script engine
408+ private static ScriptEngine getScriptEngine(String lang) {
409+ ScriptEngine se = engines.get(lang);
410+ if (se == null) {
411+ se = engineManager.getEngineByName(lang);
412+ if (se == null) {
413+ getError().println(getMessage("engine.not.found",
414+ new Object[] { lang }));
415+ System.exit(EXIT_ENGINE_NOT_FOUND);
416+ }
417+
418+ // initialize the engine
419+ initScriptEngine(se);
420+ // to avoid re-initialization of engine, store it in a map
421+ engines.put(lang, se);
422+ }
423+ return se;
424+ }
425+
426+ // initialize a given script engine
427+ private static void initScriptEngine(ScriptEngine se) {
428+ // put engine global variable
429+ se.put("engine", se);
430+
431+ // load init.<ext> file from resource
432+ List<String> exts = se.getFactory().getExtensions();
433+ InputStream sysIn = null;
434+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
435+ for (String ext : exts) {
436+ sysIn = cl.getResourceAsStream("com/sun/tools/script/shell/init." +
437+ ext);
438+ if (sysIn != null) break;
439+ }
440+ if (sysIn != null) {
441+ evaluateStream(se, sysIn, "<system-init>", null);
442+ }
443+ }
444+
445+ /**
446+ * Checks for -classpath, -cp in command line args. Creates a ClassLoader
447+ * and sets it as Thread context loader for current thread.
448+ *
449+ * @param args command line argument array
450+ */
451+ private static void checkClassPath(String[] args) {
452+ String classPath = null;
453+ for (int i = 0; i < args.length; i++) {
454+ if (args[i].equals("-classpath") ||
455+ args[i].equals("-cp")) {
456+ if (++i == args.length) {
457+ // just -classpath or -cp with no value
458+ usage(EXIT_CMD_NO_CLASSPATH);
459+ } else {
460+ classPath = args[i];
461+ }
462+ }
463+ }
464+
465+ if (classPath != null) {
466+ /* We create a class loader, configure it with specified
467+ * classpath values and set the same as context loader.
468+ * Note that ScriptEngineManager uses context loader to
469+ * load script engines. So, this ensures that user defined
470+ * script engines will be loaded. For classes referred
471+ * from scripts, Rhino engine uses thread context loader
472+ * but this is script engine dependent. We don't have
473+ * script engine independent solution anyway. Unless we
474+ * know the class loader used by a specific engine, we
475+ * can't configure correct loader.
476+ */
477+ ClassLoader parent = Main.class.getClassLoader();
478+ URL[] urls = pathToURLs(classPath);
479+ URLClassLoader loader = new URLClassLoader(urls, parent);
480+ Thread.currentThread().setContextClassLoader(loader);
481+ }
482+
483+ // now initialize script engine manager. Note that this has to
484+ // be done after setting the context loader so that manager
485+ // will see script engines from user specified classpath
486+ engineManager = new ScriptEngineManager();
487+ }
488+
489+ /**
490+ * Utility method for converting a search path string to an array
491+ * of directory and JAR file URLs.
492+ *
493+ * @param path the search path string
494+ * @return the resulting array of directory and JAR file URLs
495+ */
496+ private static URL[] pathToURLs(String path) {
497+ String[] components = path.split(File.pathSeparator);
498+ URL[] urls = new URL[components.length];
499+ int count = 0;
500+ while(count < components.length) {
501+ URL url = fileToURL(new File(components[count]));
502+ if (url != null) {
503+ urls[count++] = url;
504+ }
505+ }
506+ if (urls.length != count) {
507+ URL[] tmp = new URL[count];
508+ System.arraycopy(urls, 0, tmp, 0, count);
509+ urls = tmp;
510+ }
511+ return urls;
512+ }
513+
514+ /**
515+ * Returns the directory or JAR file URL corresponding to the specified
516+ * local file name.
517+ *
518+ * @param file the File object
519+ * @return the resulting directory or JAR file URL, or null if unknown
520+ */
521+ private static URL fileToURL(File file) {
522+ String name;
523+ try {
524+ name = file.getCanonicalPath();
525+ } catch (IOException e) {
526+ name = file.getAbsolutePath();
527+ }
528+ name = name.replace(File.separatorChar, '/');
529+ if (!name.startsWith("/")) {
530+ name = "/" + name;
531+ }
532+ // If the file does not exist, then assume that it's a directory
533+ if (!file.isFile()) {
534+ name = name + "/";
535+ }
536+ try {
537+ return new URL("file", "", name);
538+ } catch (MalformedURLException e) {
539+ throw new IllegalArgumentException("file");
540+ }
541+ }
542+
543+ private static void setScriptArguments(ScriptEngine se, String[] args) {
544+ se.put("arguments", args);
545+ se.put(ScriptEngine.ARGV, args);
546+ }
547+
548+ private static String setScriptFilename(ScriptEngine se, String name) {
549+ String oldName = (String) se.get(ScriptEngine.FILENAME);
550+ se.put(ScriptEngine.FILENAME, name);
551+ return oldName;
552+ }
553+
554+ // exit codes
555+ private static final int EXIT_SUCCESS = 0;
556+ private static final int EXIT_CMD_NO_CLASSPATH = 1;
557+ private static final int EXIT_CMD_NO_FILE = 2;
558+ private static final int EXIT_CMD_NO_SCRIPT = 3;
559+ private static final int EXIT_CMD_NO_LANG = 4;
560+ private static final int EXIT_CMD_NO_ENCODING = 5;
561+ private static final int EXIT_CMD_NO_PROPNAME = 6;
562+ private static final int EXIT_UNKNOWN_OPTION = 7;
563+ private static final int EXIT_ENGINE_NOT_FOUND = 8;
564+ private static final int EXIT_NO_ENCODING_FOUND = 9;
565+ private static final int EXIT_SCRIPT_ERROR = 10;
566+ private static final int EXIT_FILE_NOT_FOUND = 11;
567+ private static final int EXIT_MULTIPLE_STDIN = 12;
568+
569+ // default scripting language
570+ private static final String DEFAULT_LANGUAGE = "js";
571+ // list of scripts to process
572+ private static List<Command> scripts;
573+ // the script engine manager
574+ private static ScriptEngineManager engineManager;
575+ // map of engines we loaded
576+ private static Map<String, ScriptEngine> engines;
577+ // error messages resource
578+ private static ResourceBundle msgRes;
579+ private static String BUNDLE_NAME = "com.sun.tools.script.shell.messages";
580+ private static String PROGRAM_NAME = "jrunscript";
581+
582+ static {
583+ scripts = new ArrayList<Command>();
584+ engines = new HashMap<String, ScriptEngine>();
585+ msgRes = ResourceBundle.getBundle(BUNDLE_NAME, Locale.getDefault());
586+ }
587+}
java/pkg/com/sun/tools/script/shell/init.js+884−0
@@ -0,0 +1,884 @@
1+/*
2+ * Copyright (c) 2005, 2010, 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+ * jrunscript JavaScript built-in functions and objects.
28+ */
29+
30+/**
31+ * Creates an object that delegates all method calls on
32+ * it to the 'invoke' method on the given delegate object.<br>
33+ *
34+ * Example:
35+ * <pre>
36+ * <code>
37+ * var x = { invoke: function(name, args) { //code...}
38+ * var y = new JSInvoker(x);
39+ * y.func(3, 3); // calls x.invoke('func', args); where args is array of arguments
40+ * </code>
41+ * </pre>
42+ * @param obj object to be wrapped by JSInvoker
43+ * @constructor
44+ */
45+function JSInvoker(obj) {
46+ return new JSAdapter({
47+ __get__ : function(name) {
48+ return function() {
49+ return obj.invoke(name, arguments);
50+ }
51+ }
52+ });
53+}
54+
55+/**
56+ * This variable represents OS environment. Environment
57+ * variables can be accessed as fields of this object. For
58+ * example, env.PATH will return PATH value configured.
59+ */
60+var env = new JSAdapter({
61+ __get__ : function (name) {
62+ return java.lang.System.getenv(name);
63+ },
64+ __has__ : function (name) {
65+ return java.lang.System.getenv().containsKey(name);
66+ },
67+ __getIds__ : function() {
68+ return java.lang.System.getenv().keySet().toArray();
69+ },
70+ __delete__ : function(name) {
71+ println("can't delete env item");
72+ },
73+ __put__ : function (name, value) {
74+ println("can't change env item");
75+ },
76+ toString: function() {
77+ return java.lang.System.getenv().toString();
78+ }
79+});
80+
81+/**
82+ * Creates a convenient script object to deal with java.util.Map instances.
83+ * The result script object's field names are keys of the Map. For example,
84+ * scriptObj.keyName can be used to access value associated with given key.<br>
85+ * Example:
86+ * <pre>
87+ * <code>
88+ * var x = java.lang.SystemProperties();
89+ * var y = jmap(x);
90+ * println(y['java.class.path']); // prints java.class.path System property
91+ * delete y['java.class.path']; // remove java.class.path System property
92+ * </code>
93+ * </pre>
94+ *
95+ * @param map java.util.Map instance that will be wrapped
96+ * @constructor
97+ */
98+function jmap(map) {
99+ return new JSAdapter({
100+ __get__ : function(name) {
101+ if (map.containsKey(name)) {
102+ return map.get(name);
103+ } else {
104+ return undefined;
105+ }
106+ },
107+ __has__ : function(name) {
108+ return map.containsKey(name);
109+ },
110+
111+ __delete__ : function (name) {
112+ return map.remove(name);
113+ },
114+ __put__ : function(name, value) {
115+ map.put(name, value);
116+ },
117+ __getIds__ : function() {
118+ return map.keySet().toArray();
119+ },
120+ toString: function() {
121+ return map.toString();
122+ }
123+ });
124+}
125+
126+/**
127+ * Creates a convenient script object to deal with java.util.List instances.
128+ * The result script object behaves like an array. For example,
129+ * scriptObj[index] syntax can be used to access values in the List instance.
130+ * 'length' field gives size of the List. <br>
131+ *
132+ * Example:
133+ * <pre>
134+ * <code>
135+ * var x = new java.util.ArrayList(4);
136+ * x.add('Java');
137+ * x.add('JavaScript');
138+ * x.add('SQL');
139+ * x.add('XML');
140+ *
141+ * var y = jlist(x);
142+ * println(y[2]); // prints third element of list
143+ * println(y.length); // prints size of the list
144+ *
145+ * @param map java.util.List instance that will be wrapped
146+ * @constructor
147+ */
148+function jlist(list) {
149+ function isValid(index) {
150+ return typeof(index) == 'number' &&
151+ index > -1 && index < list.size();
152+ }
153+ return new JSAdapter({
154+ __get__ : function(name) {
155+ if (isValid(name)) {
156+ return list.get(name);
157+ } else if (name == 'length') {
158+ return list.size();
159+ } else {
160+ return undefined;
161+ }
162+ },
163+ __has__ : function (name) {
164+ return isValid(name) || name == 'length';
165+ },
166+ __delete__ : function(name) {
167+ if (isValid(name)) {
168+ list.remove(name);
169+ }
170+ },
171+ __put__ : function(name, value) {
172+ if (isValid(name)) {
173+ list.set(name, value);
174+ }
175+ },
176+ __getIds__: function() {
177+ var res = new Array(list.size());
178+ for (var i = 0; i < res.length; i++) {
179+ res[i] = i;
180+ }
181+ return res;
182+ },
183+ toString: function() {
184+ return list.toString();
185+ }
186+ });
187+}
188+
189+/**
190+ * This is java.lang.System properties wrapped by jmap.
191+ * For eg. to access java.class.path property, you can use
192+ * the syntax sysProps["java.class.path"]
193+ */
194+var sysProps = jmap(java.lang.System.getProperties());
195+
196+// stdout, stderr & stdin
197+var out = java.lang.System.out;
198+var err = java.lang.System.err;
199+// can't use 'in' because it is a JavaScript keyword :-(
200+var inp = java.lang.System["in"];
201+
202+// useful imports for often used io, net classes
203+importPackage(java.io);
204+importPackage(java.net);
205+
206+/**
207+ * Generic any object to input stream mapper
208+ * @param str input file name, URL or InputStream
209+ * @return InputStream object
210+ * @private
211+ */
212+function inStream(str) {
213+ if (typeof(str) == "string") {
214+ // '-' means standard input
215+ if (str == '-') {
216+ return java.lang.System["in"];
217+ }
218+ // try file first
219+ var file = null;
220+ try {
221+ file = pathToFile(str);
222+ } catch (e) {
223+ }
224+ if (file && file.exists()) {
225+ return new FileInputStream(file);
226+ } else {
227+ try {
228+ // treat the string as URL
229+ return new URL(str).openStream();
230+ } catch (e) {
231+ throw 'file or URL ' + str + ' not found';
232+ }
233+ }
234+ } else {
235+ if (str instanceof InputStream) {
236+ return str;
237+ } else if (str instanceof URL) {
238+ return str.openStream();
239+ } else if (str instanceof File) {
240+ return new FileInputStream(str);
241+ }
242+ }
243+ // everything failed, just give input stream
244+ return java.lang.System["in"];
245+}
246+
247+/**
248+ * Generic any object to output stream mapper
249+ *
250+ * @param out output file name or stream
251+ * @return OutputStream object
252+ * @private
253+ */
254+function outStream(out) {
255+ if (typeof(out) == "string") {
256+ if (out == '>') {
257+ return java.lang.System.out;
258+ } else {
259+ // treat it as file
260+ return new FileOutputStream(pathToFile(out));
261+ }
262+ } else {
263+ if (out instanceof OutputStream) {
264+ return out;
265+ } else if (out instanceof File) {
266+ return new FileOutputStream(out);
267+ }
268+ }
269+
270+ // everything failed, just return System.out
271+ return java.lang.System.out;
272+}
273+
274+/**
275+ * stream close takes care not to close stdin, out & err.
276+ * @private
277+ */
278+function streamClose(stream) {
279+ if (stream) {
280+ if (stream != java.lang.System["in"] &&
281+ stream != java.lang.System.out &&
282+ stream != java.lang.System.err) {
283+ try {
284+ stream.close();
285+ } catch (e) {
286+ println(e);
287+ }
288+ }
289+ }
290+}
291+
292+/**
293+ * Loads and evaluates JavaScript code from a stream or file or URL<br>
294+ *
295+ * Examples:
296+ * <pre>
297+ * <code>
298+ * load('test.js'); // load script file 'test.js'
299+ * load('http://java.sun.com/foo.js'); // load from a URL
300+ * </code>
301+ * </pre>
302+ *
303+ * @param str input from which script is loaded and evaluated
304+ */
305+function load(str) {
306+ var stream = inStream(str);
307+ var bstream = new BufferedInputStream(stream);
308+ var reader = new BufferedReader(new InputStreamReader(bstream));
309+ var oldFilename = engine.get(engine.FILENAME);
310+ engine.put(engine.FILENAME, str);
311+ try {
312+ engine.eval(reader);
313+ } finally {
314+ engine.put(engine.FILENAME, oldFilename);
315+ streamClose(stream);
316+ }
317+}
318+
319+// file system utilities
320+
321+/**
322+ * Creates a Java byte[] of given length
323+ * @param len size of the array to create
324+ * @private
325+ */
326+function javaByteArray(len) {
327+ return java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, len);
328+}
329+
330+var curDir = new File('.');
331+
332+/**
333+ * Print present working directory
334+ */
335+function pwd() {
336+ println(curDir.getAbsolutePath());
337+}
338+
339+/**
340+ * Changes present working directory to given directory
341+ * @param target directory to change to. optional, defaults to user's HOME
342+ */
343+function cd(target) {
344+ if (target == undefined) {
345+ target = sysProps["user.home"];
346+ }
347+ if (!(target instanceof File)) {
348+ target = pathToFile(target);
349+ }
350+ if (target.exists() && target.isDirectory()) {
351+ curDir = target;
352+ } else {
353+ println(target + " is not a directory");
354+ }
355+}
356+
357+/**
358+ * Converts path to java.io.File taking care of shell present working dir
359+ *
360+ * @param pathname file path to be converted
361+ * @private
362+ */
363+function pathToFile(pathname) {
364+ var tmp = pathname;
365+ if (!(tmp instanceof File)) {
366+ tmp = new File(tmp);
367+ }
368+ if (!tmp.isAbsolute()) {
369+ return new File(curDir, pathname);
370+ } else {
371+ return tmp;
372+ }
373+}
374+
375+/**
376+ * Copies a file or URL or stream to another file or stream
377+ *
378+ * @param from input file or URL or stream
379+ * @param to output stream or file
380+ */
381+function cp(from, to) {
382+ if (from == to) {
383+ println("file " + from + " cannot be copied onto itself!");
384+ return;
385+ }
386+ var inp = inStream(from);
387+ var out = outStream(to);
388+ var binp = new BufferedInputStream(inp);
389+ var bout = new BufferedOutputStream(out);
390+ var buff = javaByteArray(1024);
391+ var len;
392+ while ((len = binp.read(buff)) > 0 )
393+ bout.write(buff, 0, len);
394+
395+ bout.flush();
396+ streamClose(inp);
397+ streamClose(out);
398+}
399+
400+/**
401+ * Shows the content of a file or URL or any InputStream<br>
402+ * Examples:
403+ * <pre>
404+ * <code>
405+ * cat('test.txt'); // show test.txt file contents
406+ * cat('http://java.net'); // show the contents from the URL http://java.net
407+ * </code>
408+ * </pre>
409+ * @param obj input to show
410+ * @param pattern optional. show only the lines matching the pattern
411+ */
412+function cat(obj, pattern) {
413+ if (obj instanceof File && obj.isDirectory()) {
414+ ls(obj);
415+ return;
416+ }
417+
418+ var inp = null;
419+ if (!(obj instanceof Reader)) {
420+ inp = inStream(obj);
421+ obj = new BufferedReader(new InputStreamReader(inp));
422+ }
423+ var line;
424+ if (pattern) {
425+ var count = 1;
426+ while ((line=obj.readLine()) != null) {
427+ if (line.match(pattern)) {
428+ println(count + "\t: " + line);
429+ }
430+ count++;
431+ }
432+ } else {
433+ while ((line=obj.readLine()) != null) {
434+ println(line);
435+ }
436+ }
437+}
438+
439+/**
440+ * Returns directory part of a filename
441+ *
442+ * @param pathname input path name
443+ * @return directory part of the given file name
444+ */
445+function dirname(pathname) {
446+ var dirName = ".";
447+ // Normalize '/' to local file separator before work.
448+ var i = pathname.replace('/', File.separatorChar ).lastIndexOf(
449+ File.separator );
450+ if ( i != -1 )
451+ dirName = pathname.substring(0, i);
452+ return dirName;
453+}
454+
455+/**
456+ * Creates a new dir of given name
457+ *
458+ * @param dir name of the new directory
459+ */
460+function mkdir(dir) {
461+ var dir = pathToFile(dir);
462+ println(dir.mkdir()? "created" : "can not create dir");
463+}
464+
465+/**
466+ * Creates the directory named by given pathname, including
467+ * any necessary but nonexistent parent directories.
468+ *
469+ * @param dir input path name
470+ */
471+function mkdirs(dir) {
472+ var dir = pathToFile(dir);
473+ println(dir.mkdirs()? "created" : "can not create dirs");
474+}
475+
476+/**
477+ * Removes a given file
478+ *
479+ * @param pathname name of the file
480+ */
481+function rm(pathname) {
482+ file = pathToFile(pathname);
483+ if (!file.exists()) {
484+ println("file not found: " + pathname);
485+ return false;
486+ }
487+ // note that delete is a keyword in JavaScript!
488+ println(file["delete"]()? "deleted" : "can not delete");
489+}
490+
491+/**
492+ * Removes a given directory
493+ *
494+ * @param pathname name of the directory
495+ */
496+function rmdir(pathname) {
497+ rm(pathname);
498+}
499+
500+/**
501+ * Synonym for 'rm'
502+ */
503+function del(pathname) {
504+ rm(pathname);
505+}
506+
507+/**
508+ * Moves a file to another
509+ *
510+ * @param from original name of the file
511+ * @param to new name for the file
512+ */
513+function mv(from, to) {
514+ println(pathToFile(from).renameTo(pathToFile(to))?
515+ "moved" : "can not move");
516+}
517+
518+/**
519+ * Synonym for 'mv'.
520+ */
521+function ren(from, to) {
522+ mv(from, to);
523+}
524+
525+var months = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
526+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ];
527+
528+/**
529+ * Helper function called by ls
530+ * @private
531+ */
532+function printFile(f) {
533+ var sb = new java.lang.StringBuffer();
534+ sb.append(f.isDirectory()? "d" : "-");
535+ sb.append(f.canRead() ? "r": "-" );
536+ sb.append(f.canWrite() ? "w": "-" );
537+ sb.append(" ");
538+
539+ var d = new java.util.Date(f.lastModified());
540+ var c = new java.util.GregorianCalendar();
541+ c.setTime(d);
542+ var day = c.get(java.util.Calendar.DAY_OF_MONTH);
543+ sb.append(months[c.get(java.util.Calendar.MONTH)]
544+ + " " + day );
545+ if (day < 10) {
546+ sb.append(" ");
547+ }
548+
549+ // to get fixed length 'length' field
550+ var fieldlen = 8;
551+ var len = new java.lang.StringBuffer();
552+ for(var j=0; j<fieldlen; j++)
553+ len.append(" ");
554+ len.insert(0, java.lang.Long.toString(f.length()));
555+ len.setLength(fieldlen);
556+ // move the spaces to the front
557+ var si = len.toString().indexOf(" ");
558+ if ( si != -1 ) {
559+ var pad = len.toString().substring(si);
560+ len.setLength(si);
561+ len.insert(0, pad);
562+ }
563+ sb.append(len.toString());
564+ sb.append(" ");
565+ sb.append(f.getName());
566+ if (f.isDirectory()) {
567+ sb.append('/');
568+ }
569+ println(sb.toString());
570+}
571+
572+/**
573+ * Lists the files in a directory
574+ *
575+ * @param dir directory from which to list the files. optional, default to pwd
576+ * @param filter pattern to filter the files listed. optional, default is '.'.
577+ */
578+function ls(dir, filter) {
579+ if (dir) {
580+ dir = pathToFile(dir);
581+ } else {
582+ dir = curDir;
583+ }
584+ if (dir.isDirectory()) {
585+ var files = dir.listFiles();
586+ for (var i in files) {
587+ var f = files[i];
588+ if (filter) {
589+ if(!f.getName().match(filter)) {
590+ continue;
591+ }
592+ }
593+ printFile(f);
594+ }
595+ } else {
596+ printFile(dir);
597+ }
598+}
599+
600+/**
601+ * Synonym for 'ls'.
602+ */
603+function dir(d, filter) {
604+ ls(d, filter);
605+}
606+
607+/**
608+ * Unix-like grep, but accepts JavaScript regex patterns
609+ *
610+ * @param pattern to search in files
611+ * @param files one or more files
612+ */
613+function grep(pattern, files /*, one or more files */) {
614+ if (arguments.length < 2) return;
615+ for (var i = 1; i < arguments.length; i++) {
616+ println(arguments[i] + ":");
617+ cat(arguments[i], pattern);
618+ }
619+}
620+
621+/**
622+ * Find in files. Calls arbitrary callback function
623+ * for each matching file.<br>
624+ *
625+ * Examples:
626+ * <pre>
627+ * <code>
628+ * find('.')
629+ * find('.', '.*\.class', rm); // remove all .class files
630+ * find('.', '.*\.java'); // print fullpath of each .java file
631+ * find('.', '.*\.java', cat); // print all .java files
632+ * </code>
633+ * </pre>
634+ *
635+ * @param dir directory to search files
636+ * @param pattern to search in the files
637+ * @param callback function to call for matching files
638+ */
639+function find(dir, pattern, callback) {
640+ dir = pathToFile(dir);
641+ if (!callback) callback = print;
642+ var files = dir.listFiles();
643+ for (var f in files) {
644+ var file = files[f];
645+ if (file.isDirectory()) {
646+ find(file, pattern, callback);
647+ } else {
648+ if (pattern) {
649+ if (file.getName().match(pattern)) {
650+ callback(file);
651+ }
652+ } else {
653+ callback(file);
654+ }
655+ }
656+ }
657+}
658+
659+// process utilities
660+
661+/**
662+ * Exec's a child process, waits for completion &amp; returns exit code
663+ *
664+ * @param cmd command to execute in child process
665+ */
666+function exec(cmd) {
667+ var process = java.lang.Runtime.getRuntime().exec(cmd);
668+ var inp = new DataInputStream(process.getInputStream());
669+ var line = null;
670+ while ((line = inp.readLine()) != null) {
671+ println(line);
672+ }
673+ process.waitFor();
674+ $exit = process.exitValue();
675+}
676+
677+/**
678+ * Exit the shell program.
679+ *
680+ * @param exitCode integer code returned to OS shell.
681+ * optional, defaults to 0
682+ */
683+function exit(code) {
684+ if (code) {
685+ java.lang.System.exit(code + 0);
686+ } else {
687+ java.lang.System.exit(0);
688+ }
689+}
690+
691+/**
692+ * synonym for exit
693+ */
694+function quit(code) {
695+ exit(code);
696+}
697+
698+// XML utilities
699+
700+/**
701+ * Converts input to DOM Document object
702+ *
703+ * @param inp file or reader. optional, without this param,
704+ * this function returns a new DOM Document.
705+ * @return returns a DOM Document object
706+ */
707+function XMLDocument(inp) {
708+ var factory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
709+ var builder = factory.newDocumentBuilder();
710+ if (inp) {
711+ if (typeof(inp) == "string") {
712+ return builder.parse(pathToFile(inp));
713+ } else {
714+ return builder.parse(inp);
715+ }
716+ } else {
717+ return builder.newDocument();
718+ }
719+}
720+
721+/**
722+ * Converts arbitrary stream, file, URL to XMLSource
723+ *
724+ * @param inp input stream or file or URL
725+ * @return XMLSource object
726+ */
727+function XMLSource(inp) {
728+ if (inp instanceof javax.xml.transform.Source) {
729+ return inp;
730+ } else if (inp instanceof Packages.org.w3c.dom.Document) {
731+ return new javax.xml.transform.dom.DOMSource(inp);
732+ } else {
733+ inp = new BufferedInputStream(inStream(inp));
734+ return new javax.xml.transform.stream.StreamSource(inp);
735+ }
736+}
737+
738+/**
739+ * Converts arbitrary stream, file to XMLResult
740+ *
741+ * @param inp output stream or file
742+ * @return XMLResult object
743+ */
744+function XMLResult(out) {
745+ if (out instanceof javax.xml.transform.Result) {
746+ return out;
747+ } else if (out instanceof Packages.org.w3c.dom.Document) {
748+ return new javax.xml.transform.dom.DOMResult(out);
749+ } else {
750+ out = new BufferedOutputStream(outStream(out));
751+ return new javax.xml.transform.stream.StreamResult(out);
752+ }
753+}
754+
755+/**
756+ * Perform XSLT transform
757+ *
758+ * @param inp Input XML to transform (URL, File or InputStream)
759+ * @param style XSL Stylesheet to be used (URL, File or InputStream). optional.
760+ * @param out Output XML (File or OutputStream
761+ */
762+function XSLTransform(inp, style, out) {
763+ switch (arguments.length) {
764+ case 2:
765+ inp = arguments[0];
766+ out = arguments[1];
767+ break;
768+ case 3:
769+ inp = arguments[0];
770+ style = arguments[1];
771+ out = arguments[2];
772+ break;
773+ default:
774+ println("XSL tranform requires 2 or 3 arguments");
775+ return;
776+ }
777+
778+ var factory = javax.xml.transform.TransformerFactory.newInstance();
779+ var tranformer;
780+ if (style) {
781+ transformer = factory.newTransformer(XMLSource(style));
782+ } else {
783+ transformer = factory.newTransformer();
784+ }
785+ var source = XMLSource(inp);
786+ var result = XMLResult(out);
787+ transformer.transform(source, result);
788+ if (source.getInputStream) {
789+ streamClose(source.getInputStream());
790+ }
791+ if (result.getOutputStream) {
792+ streamClose(result.getOutputStream());
793+ }
794+}
795+
796+// miscellaneous utilities
797+
798+/**
799+ * Prints which command is selected from PATH
800+ *
801+ * @param cmd name of the command searched from PATH
802+ */
803+function which(cmd) {
804+ var st = new java.util.StringTokenizer(env.PATH, File.pathSeparator);
805+ while (st.hasMoreTokens()) {
806+ var file = new File(st.nextToken(), cmd);
807+ if (file.exists()) {
808+ println(file.getAbsolutePath());
809+ return;
810+ }
811+ }
812+}
813+
814+/**
815+ * Prints IP addresses of given domain name
816+ *
817+ * @param name domain name
818+ */
819+function ip(name) {
820+ var addrs = InetAddress.getAllByName(name);
821+ for (var i in addrs) {
822+ println(addrs[i]);
823+ }
824+}
825+
826+/**
827+ * Prints current date in current locale
828+ */
829+function date() {
830+ println(new Date().toLocaleString());
831+}
832+
833+/**
834+ * Echoes the given string arguments
835+ */
836+function echo(x) {
837+ for (var i = 0; i < arguments.length; i++) {
838+ println(arguments[i]);
839+ }
840+}
841+
842+/**
843+ * This is C-like printf
844+ *
845+ * @param format string to format the rest of the print items
846+ * @param args variadic argument list
847+ */
848+function printf(format, args/*, more args*/) {
849+ var array = java.lang.reflect.Array.newInstance(java.lang.Object,
850+ arguments.length - 1);
851+ for (var i = 0; i < array.length; i++) {
852+ array[i] = arguments[i+1];
853+ }
854+ return java.lang.System.out.printf(format, array);
855+}
856+
857+/**
858+ * Reads one or more lines from stdin after printing prompt
859+ *
860+ * @param prompt optional, default is '>'
861+ * @param multiline to tell whether to read single line or multiple lines
862+ */
863+function read(prompt, multiline) {
864+ if (!prompt) {
865+ prompt = '>';
866+ }
867+ var inp = java.lang.System["in"];
868+ var reader = new BufferedReader(new InputStreamReader(inp));
869+ if (multiline) {
870+ var line = '';
871+ while (true) {
872+ java.lang.System.err.print(prompt);
873+ java.lang.System.err.flush();
874+ var tmp = reader.readLine();
875+ if (tmp == '' || tmp == null) break;
876+ line += tmp + '\n';
877+ }
878+ return line;
879+ } else {
880+ java.lang.System.err.print(prompt);
881+ java.lang.System.err.flush();
882+ return reader.readLine();
883+ }
884+}
java/pkg/com/sun/tools/script/shell/messages.properties+66−0
@@ -0,0 +1,66 @@
1+#
2+# Copyright (c) 2005, 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+string.script.error=\
27+ script error: {0}
28+
29+file.script.error=\
30+ script error in file {0} : {1}
31+
32+file.not.found=\
33+ script file {0} is not found
34+
35+engine.not.found=\
36+ script engine for language {0} can not be found
37+
38+engine.info=\
39+ Language {0} {1} implemention "{2}" {3}
40+
41+encoding.unsupported=\
42+ encoding {0} is not supported
43+
44+main.usage=\
45+Usage: {0} [options] [arguments...]\n\
46+\n\
47+where [options] include:\n\
48+\ \-classpath <path> Specify where to find user class files \n\
49+\ \-cp <path> Specify where to find user class files \n\
50+\ \-D<name>=<value> Set a system property \n\
51+\ \-J<flag> Pass <flag> directly to the runtime system \n\
52+\ \-l <language> Use specified scripting language \n\
53+\ \-e <script> Evaluate given script \n\
54+\ \-encoding <encoding> Specify character encoding used by script files \n\
55+\ \-f <script file> Evaluate given script file \n\
56+\ \-f - Interactive mode, read script from standard input \n\
57+\ \ If this is used, this should be the last -f option \n\
58+\ \-help Print this usage message and exit \n\
59+\ \-? Print this usage message and exit \n\
60+\ \-q List all scripting engines available and exit \n\
61+\ \n\
62+If [arguments..] are present and if no -e or -f option is used, then first\n\
63+argument is script file and the rest of the arguments, if any, are passed\n\
64+as script arguments. If [arguments..] and -e or -f option is used, then all\n\
65+[arguments..] are passed as script arguments. If [arguments..], -e, -f are\n\
66+missing, then interactive mode is used.
java/pkg/com/sun/tools/script/shell/mkfile+8−0
@@ -0,0 +1,8 @@
1+<../../../../../../../mkconfig
2+
3+TARG=\
4+ Main.dis\
5+
6+DISBIN=$ROOT/java/dis/java/java/com/sun/tools/script/shell
7+
8+<$ROOT/mkfiles/mkjava