« Bashj programming guide » : différence entre les versions
Aucun résumé des modifications |
Aucun résumé des modifications |
||
(17 versions intermédiaires par le même utilisateur non affichées) | |||
Ligne 1 : | Ligne 1 : | ||
This is a complement to the general [[Project_bashj_:_a_bash_mutant_with_java_support|bashj |
This is a complement to the general [[Project_bashj_:_a_bash_mutant_with_java_support|bashj introduction page]]. |
||
Here is the [[Project_bashj_:_a_bash_mutant_with_java_support#Installation|bashj install]] link. |
|||
== Understanding the architecture of bashj == |
== Understanding the architecture of bashj == |
||
Ligne 17 : | Ligne 19 : | ||
But the developper of a bashj script should be aware of the fact that any global component of the JVM (static variables, Threads,...) will be shared with all other bashj clients launched. |
But the developper of a bashj script should be aware of the fact that any global component of the JVM (static variables, Threads,...) will be shared with all other bashj clients launched. |
||
For instance if a client modifies a static variable during the execution of a bashj script, the next execution of the same script will start with the modified value of that variable. This may be convenient ... or |
For instance if a client modifies a static variable during the execution of a bashj script, the next execution of the same script will start with the modified value of that variable. This may be convenient ... or a benefit, depending on situations. |
||
Similarly, if a bashj client launches a Thread without closing it, this Thread will survive in the server JVM (which may not be the intention). |
Similarly, if a bashj client launches a Thread without closing it, this Thread will survive in the server JVM (which may not be the intention). |
||
Ligne 31 : | Ligne 33 : | ||
=== Header === |
=== Header === |
||
The shebang header is a mandatory line |
The file shebang header is a mandatory line |
||
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;">#!/usr/bin/bashj</div> |
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">#!/usr/bin/bashj</span></div> |
||
=== Java section === |
=== Java section === |
||
Ligne 38 : | Ligne 40 : | ||
The java section starts with a line |
The java section starts with a line |
||
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;">#!java</div> |
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">#!java</span></div> |
||
and it ends with one of the lines |
and it ends with one of the lines |
||
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;">#!bashj</div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;">#!bash</div> |
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">#!bashj</span></div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">#!bash</span></div> |
||
The java section is similar to a java class source. However, the <span style="font-family:courier new,courier,monospace;">package</span> line, the <span style="font-family:courier new,courier,monospace;">class</span> line and the class global braces are omitted. |
The java section is similar to a java class source. However, the <span style="font-family:courier new,courier,monospace;">package</span> line, the <span style="font-family:courier new,courier,monospace;">class</span> line and the class global braces are omitted. |
||
Ligne 47 : | Ligne 49 : | ||
Only public static will be accessible from the bashj section. A line starting with static is considered as public. |
Only public static will be accessible from the bashj section. A line starting with static is considered as public. |
||
The implicit className is "'''j'''". So a function public '''<span style="font-family:courier new,courier,monospace;">static int factorial(int n)</span>''' will be called in the script bash |
The implicit className is "'''j'''". So a function <span style="font-family:courier new,courier,monospace;">'''public'''</span> '''<span style="font-family:courier new,courier,monospace;">static int factorial(int n)</span>''' will be called in the script bash section as '''<span style="font-family:courier new,courier,monospace;">j.factorial(int)</span>.''' |
||
Calling |
Calling getClass().getName() is allowed but will provide unusable and irrelevant results. |
||
=== Bash / bashj section === |
=== Bash / bashj section === |
||
This section is also optional. |
|||
If absent, the execution becomes a pure java 'interpreter' (see below). |
If absent, the execution becomes a pure java 'interpreter' (see below). |
||
Ligne 71 : | Ligne 73 : | ||
It is ''recommended'' not to use complex bash expressions as arguments to java method calls. |
It is ''recommended'' not to use complex bash expressions as arguments to java method calls. |
||
It is ''recommended and often necessary'' to use double quotes vars as arguments to java calls (to handle spaces, comma, parenthesis and other |
It is ''recommended and often necessary'' to use double quotes vars as arguments to java calls (to handle spaces, comma, parenthesis and other special shell characters). |
||
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">WORD="Hello, world ()#\$!"</span></div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">LETTER=w</span></div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">echo "index of [$LETTER] in [$WORD] is" u.indexOf("$WORD","$LETTER")</span></div> |
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">WORD="Hello, world ()#\$!"</span></div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">LETTER=w</span></div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">echo "index of [$LETTER] in [$WORD] is" u.indexOf("$WORD","$LETTER")</span></div> |
||
Java static fields are detected like java methods |
Java static fields are detected like java methods. For instance |
||
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;">piValue=Math.PI</div> |
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">piValue=Math.PI</span></div> |
||
Knowing how the detection / substitution works, it is the developer responsibility to avoid in the bash section unintended detectable expressions. The source processor is unable to handle and avoid all complex bash constructions. For instance this bash line |
Knowing how the detection / substitution works, it is the developer responsibility to avoid in the bash section unintended detectable expressions. The source processor is unable to handle and avoid all complex bash constructions. For instance this bash line |
||
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;">tr Math.PI z < $FILE # Noooo !</div> |
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">tr Math.PI z < $FILE # Noooo !</span></div> |
||
is strange but valid with bash, but it is likely to raise unwanted results with bashj... |
is strange but valid with bash, but it is likely to raise unwanted results with bashj... |
||
⚫ | |||
⚫ | |||
⚫ | *Those defined in the beginning of the running bashj script itself in the java section. Java methods are defined there without package name and without class name. The implicit class name is "'''j'''". So a function '''public static int factorial(int n)''' may be called in the script bash body as '''j.factorial(int)''' |
||
*Those present in the standard java classes ('''java.lang.System''' , '''java.lang.Math''' etc ...). The list of standard classes is defined in <span style="font-family:courier new,courier,monospace;">/opt/bashj/import</span> file. It is extensible and configurable. |
|||
⚫ | |||
⚫ | <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.info() # simple info provided by the running bashj server</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.status() # detailed info provided by the running bashj server</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.classes() # classes accessible using bashj</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.classes(String grep) # filtered classes accessible using bashj</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.methods() # methods accessible using bashj</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.methods(String grep) # filtered methods accessible using bashj</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.fields() # fields accessible using bashj</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.fields(String grep) # filtered fields accessible using bashj</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.scriptName() # name of current script</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.serverPid() # server process id</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.accessibleClass(String className) # Checks access to a given class</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.uDoc() # documentation on the global list of u methods</span></div> |
||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">A="Hello, world"</span></div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">B="or"</span></div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">C=u.indexOf("$A","$B")</span></div> |
||
⚫ | |||
⚫ | <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">CONFIRM=u.swingConfirm("$TITLE","$QUESTION")</span></div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">if [ $CONFIRM == true ] ... else ...</span></div> |
||
⚫ | |||
⚫ | |||
== From bash to bashj == |
== From bash to bashj == |
||
⚫ | |||
The bashj interpreter only works for scripts. It may not be used for an interactive session. |
The bashj interpreter only works for scripts. It may not be used for an interactive session. |
||
However It is also possible to use interactively calls to the bashj interpreter: |
|||
⚫ | |||
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">bashj "u.doubleEval(x*cos(x),0.25)"</span></div> |
|||
<span style="font-family:arial,helvetica,sans-serif;">and to put in bash scripts:</span> |
|||
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">FX=`bashj "u.doubleEval(x*cos(x),0.25)"`</span></div> |
|||
== Modularity and extensibility == |
|||
Java classes and packages are easy to add to bashj. The steps are simple: |
|||
⚫ | |||
*create anywhere one or many java classes with some static public methods and/or fields. |
|||
⚫ | |||
*compile them and put the class file(s) in a jar file |
|||
*place this jar in the directory <span style="font-family:courier new,courier,monospace;">/opt/bashj/jarlib</span> |
|||
⚫ | *Those defined in the beginning of the running bashj script itself in the java section. Java methods are defined there without package name and without class name. The implicit class name is "'''j'''". So a function public static int factorial(int n) may be called in the script bash body as '''j.factorial(int) |
||
*restart the bashj server using <span style="font-family:courier new,courier,monospace;">bashj -restart </span> |
|||
*Those present in the standard java packages '''java.lang.System''' and '''java.lang.Math''' (possibly more later if requested). |
|||
*Any script has now the capacity to call the new methods and fields in both the java section and the bashj section. |
|||
⚫ | |||
⚫ | <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.info() # simple info provided by the running bashj server</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.status() # detailed info provided by the running bashj server</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.classes() # classes accessible using bashj</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.classes(String grep) # filtered classes accessible using bashj</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.methods() # methods accessible using bashj</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.methods(String grep) # filtered methods accessible using bashj</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.fields() # fields accessible using bashj</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.fields(String grep) # filtered fields accessible using bashj</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.scriptName() # name of current script</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.serverPid() # server process id</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.accessibleClass(String className) # Checks access to a given class</span></div> <div style="background: rgb(238, 238, 238); border: 1px solid rgb(204, 204, 204); padding: 5px 10px; margin-left: 80px;"><span style="font-family:courier new,courier,monospace;">u.uDoc() # |
||
⚫ | |||
⚫ | |||
== Concurrency issues == |
== Concurrency issues == |
||
Concurrent execution of multiple bashj scripts will raise problems if some of the called methods are blocking. This happens for sleeping Threads, for UI blocking dialogs, and possibly for any method waiting for delayed results. The server processes all calls sequentially [ improvement expected ]. |
Concurrent execution of multiple bashj scripts will raise problems if some of the called methods are blocking. This happens for sleeping Threads, for UI blocking dialogs, and possibly for any method waiting for delayed results. The server processes all calls sequentially [ improvement expected ? ]. |
||
2 simple workarounds for this |
2 simple workarounds for this |
||
Ligne 104 : | Ligne 130 : | ||
*organize and use only methods providing rapid answers; or |
*organize and use only methods providing rapid answers; or |
||
*avoid concurrent executions of bashj scripts |
*avoid concurrent executions of bashj scripts |
||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
'''Multiple call of a method.''' It is not allowed to call mote than once in a bash '''line''' a given java method. Use multiple lines for multiple calls to the same method. |
|||
⚫ | |||
== Using bashj as a pure java 'interpreter' == |
== Using bashj as a pure java 'interpreter' == |
||
It is possible to create a bashj page without any bash line. In this case, the interpreter will automatically call and execute the method <span style="font-family:courier new,courier,monospace;">static void main(String... a)</span> , as in this example: |
It is possible to create a bashj page without any bash line. In this case, the interpreter will automatically call and execute the method <span style="font-family:courier new,courier,monospace;">static void main(String... a)</span> , as in this example: |
||
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;">#!/usr/bin/bashj<br/> #!java</div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;">static void main(String... a)<br/> {u.p("Hello world, welcome to bashj");}</div> |
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">#!/usr/bin/bashj<br/> #!java</span></div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">static void main(String... a)<br/> {u.p("Hello world, welcome to bashj");}</span></div> |
||
This minimal but complete code will execute as expected. |
This minimal but complete code will execute as expected. "Interpreter" is not what people would probably expect: the code is actually executed through the server JVM. |
||
== Convenience u methods == |
== Convenience u methods == |
||
Various convenience methods are include with bashj. It is recommended to cheks their list using the command |
Various convenience methods are include with bashj. It is recommended to cheks their list using the command |
||
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">bashj |
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">bashj +uDoc</span></div> |
||
or their javadoc. |
or their javadoc. |
||
== Swinging bash == |
== Swinging bash (bash with swing user interface) == |
||
As any other java package, it is possible to take advantage of Swing UI components, and this provides (through bashj) a windowing interface to bash. |
As any other java package, it is possible to take advantage of Swing UI components, and this provides (through bashj) a windowing interface to bash. |
||
Here is a minimal example: |
Here is a minimal example: |
||
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;">#!/usr/bin/bashj<br/> #!java<br/> import javax.swing.JFrame;<br/> import javax.swing.JOptionPane;</div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;">static void main(String... a)<br/> {JOptionPane.showMessageDialog(new JFrame(),"Welcome to bashj swing UI");}</div> |
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">#!/usr/bin/bashj<br/> #!java<br/> import javax.swing.JFrame;<br/> import javax.swing.JOptionPane;</span></div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">static void main(String... a)<br/> {JOptionPane.showMessageDialog(new JFrame(),"Welcome to bashj swing UI");}</span></div> |
||
The same swing tasks may be achieved using convenient u methods: |
The same swing tasks may be achieved using convenient '''u''' methods: |
||
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;">#!/usr/bin/bashj</div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;">TITLE="bashj msg"<br/> MSG="Welcome to bashj swing UI"<br/> u.swingInfo("$TITLE","$MSG")<br/> ERMSG="There is a problem!"<br/> u.swingError("$TITLE","$ERMSG")<br/> QUESTION="Do you confirm ?"<br/> CON=u.swingConfirm("$TITLE","$QUESTION")</div> |
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">#!/usr/bin/bashj</span></div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">TITLE="bashj msg"<br/> MSG="Welcome to bashj swing UI"<br/> u.swingInfo("$TITLE","$MSG")<br/> ERMSG="There is a problem!"<br/> u.swingError("$TITLE","$ERMSG")<br/> QUESTION="Do you confirm ?"<br/> CON=u.swingConfirm("$TITLE","$QUESTION")</span></div> |
||
== Inter process communication using bashj == |
== Inter process communication using bashj == |
||
Ligne 142 : | Ligne 156 : | ||
The following u methods allow to set() and get() inter process variables: |
The following u methods allow to set() and get() inter process variables: |
||
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;">public static void set(String key,String value,boolean scriptSpecific,boolean persist)<br/> public static String get(String key,boolean scriptSpecific,boolean persist)</div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;">public static void set(String key,String value)<br/> public static String get(String key)</div> |
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">public static void set(String key,String value,boolean scriptSpecific,boolean persist)<br/> public static String get(String key,boolean scriptSpecific,boolean persist)</span></div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-family:courier new,courier,monospace;">public static void set(String key,String value)<br/> public static String get(String key)</span></div> |
||
The <span style="font-family:courier new,courier,monospace;">scriptSpecific</span> flag indicates whether this value is shared or not with other scripts. These values will be kept during successive calls of the calling scripts, until the server is stopped. |
The <span style="font-family:courier new,courier,monospace;">scriptSpecific</span> flag indicates whether this value is shared or not with other scripts. These values will be kept during successive calls of the calling scripts, until the server is stopped. |
||
Ligne 148 : | Ligne 162 : | ||
The simple calls (without boolean parameters) assume scriptSpecific is true, persist is false. |
The simple calls (without boolean parameters) assume scriptSpecific is true, persist is false. |
||
|
|||
== Script coding examples == |
== Script coding examples == |
||
Here are some |
Here are some basic examples, extracted from the wider list of examples provided as part of the installation process (<span style="font-family:courier new,courier,monospace;">example</span> subdir). |
||
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-size:small;"><code>#!/usr/bin/bashj</code></span></div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-size:small;"><code>#!java</code></span></div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-size:small;"><code>static int factorial(int n) <br/> {if (n<=0) return(0);<br/> if (n==1) return(1);<br/> return(n*factorial(n-1));}</code></span></div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-size:small;"><code>#!bashj</code></span></div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-size:small;"><code>echo j.factorial(10)</code></span></div> |
<div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-size:small;"><code>#!/usr/bin/bashj</code></span></div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-size:small;"><code>#!java</code></span></div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-size:small;"><code>static int factorial(int n) <br/> {if (n<=0) return(0);<br/> if (n==1) return(1);<br/> return(n*factorial(n-1));}</code></span></div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-size:small;"><code>#!bashj</code></span></div> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"><span style="font-size:small;"><code>echo j.factorial(10)</code></span></div> |
||
|
|
Dernière version du 11 juillet 2018 à 19:30
This is a complement to the general bashj introduction page.
Here is the bashj install link.
Understanding the architecture of bashj
The key idea behind bashj is the execution of a bashj server. It is a JVM instance performing essentially two tasks
- translate bashj code into bash code
- execute any java method call for any running bashj client
The benefit of this is the extreme efficiency of this minimal architecture, taking advantage of combined strengths of java & bash.
The following slide explains the global flows of bashj
But the developper of a bashj script should be aware of the fact that any global component of the JVM (static variables, Threads,...) will be shared with all other bashj clients launched.
For instance if a client modifies a static variable during the execution of a bashj script, the next execution of the same script will start with the modified value of that variable. This may be convenient ... or a benefit, depending on situations.
Similarly, if a bashj client launches a Thread without closing it, this Thread will survive in the server JVM (which may not be the intention).
Composition of a bashj script file
A bashj script contains typically 3 components
- the header
- the java section
- the bash / bashj section
Header
The file shebang header is a mandatory line
Java section
The java section is optional. Without this part, the script behaves exactly as a bash script file with the same content.
The java section starts with a line
and it ends with one of the lines
The java section is similar to a java class source. However, the package line, the class line and the class global braces are omitted.
It is possible (and often necessary) to include import lines.
Only public static will be accessible from the bashj section. A line starting with static is considered as public.
The implicit className is "j". So a function public static int factorial(int n) will be called in the script bash section as j.factorial(int).
Calling getClass().getName() is allowed but will provide unusable and irrelevant results.
Bash / bashj section
This section is also optional.
If absent, the execution becomes a pure java 'interpreter' (see below).
If present, it includes standard bash lines, with the possible presence of java calls.
The java call translation is enabled with the directive
and disabled with the directive
The java calls are detected by the source processor thread when the translation is enabled. They are coded in either form:
For instance
The result of such calls may be used to produce bash shell values, and for instance:
It is recommended not to use complex bash expressions as arguments to java method calls.
It is recommended and often necessary to use double quotes vars as arguments to java calls (to handle spaces, comma, parenthesis and other special shell characters).
Java static fields are detected like java methods. For instance
Knowing how the detection / substitution works, it is the developer responsibility to avoid in the bash section unintended detectable expressions. The source processor is unable to handle and avoid all complex bash constructions. For instance this bash line
is strange but valid with bash, but it is likely to raise unwanted results with bashj...
Java calls in bashj section
Several families of java methods & fields may be called
- Those defined in the beginning of the running bashj script itself in the java section. Java methods are defined there without package name and without class name. The implicit class name is "j". So a function public static int factorial(int n) may be called in the script bash body as j.factorial(int)
- Those present in the standard java classes (java.lang.System , java.lang.Math etc ...). The list of standard classes is defined in /opt/bashj/import file. It is extensible and configurable.
- The control methods provided by the bashj server:
- Those provided as utilities as part of bashj. They are also accessible with a class name "u", for instance u.toUpperCase(String) or yellow(String). The list is available using bashj +uDoc. It frequently grows.
- Those present in jars put by the user in the subdirectory jarlib. This allows users to easily extend bashj capabilities, and to possibly create bash/bashj modules.
Coding rules
String arguments : String arguments should always be double quoted in the bashj section. The correct way to use String arguments is:
Boolean returned values. Bash and java have very different concepts related to booleans. To test return values of boolean java calls, use this:
Special characters. It is not allowed to use some greek characters φ χ ψ τ h in bashj sources (they are detected and used by the preprocessor).
Embedded calls. It is not possible to embed bashj java method calls ( Math.log(Math.sin($X)) will not work).
From bash to bashj
A bashj file is similar to a standard bash file. Just replace the shebang : #!/usr/bin/bashj instead of #!/bin/bash. A bash script will be processed by bashj exactly like it is processed by bash.
The bashj interpreter only works for scripts. It may not be used for an interactive session.
However It is also possible to use interactively calls to the bashj interpreter:
and to put in bash scripts:
Modularity and extensibility
Java classes and packages are easy to add to bashj. The steps are simple:
- create anywhere one or many java classes with some static public methods and/or fields.
- compile them and put the class file(s) in a jar file
- place this jar in the directory /opt/bashj/jarlib
- restart the bashj server using bashj -restart
- Any script has now the capacity to call the new methods and fields in both the java section and the bashj section.
Concurrency issues
Concurrent execution of multiple bashj scripts will raise problems if some of the called methods are blocking. This happens for sleeping Threads, for UI blocking dialogs, and possibly for any method waiting for delayed results. The server processes all calls sequentially [ improvement expected ? ].
2 simple workarounds for this
- organize and use only methods providing rapid answers; or
- avoid concurrent executions of bashj scripts
Using bashj as a pure java 'interpreter'
It is possible to create a bashj page without any bash line. In this case, the interpreter will automatically call and execute the method static void main(String... a) , as in this example:
#!java
{u.p("Hello world, welcome to bashj");}
This minimal but complete code will execute as expected. "Interpreter" is not what people would probably expect: the code is actually executed through the server JVM.
Convenience u methods
Various convenience methods are include with bashj. It is recommended to cheks their list using the command
or their javadoc.
Swinging bash (bash with swing user interface)
As any other java package, it is possible to take advantage of Swing UI components, and this provides (through bashj) a windowing interface to bash.
Here is a minimal example:
#!java
import javax.swing.JFrame;
import javax.swing.JOptionPane;
{JOptionPane.showMessageDialog(new JFrame(),"Welcome to bashj swing UI");}
The same swing tasks may be achieved using convenient u methods:
MSG="Welcome to bashj swing UI"
u.swingInfo("$TITLE","$MSG")
ERMSG="There is a problem!"
u.swingError("$TITLE","$ERMSG")
QUESTION="Do you confirm ?"
CON=u.swingConfirm("$TITLE","$QUESTION")
Inter process communication using bashj
Given the persistence features of the bashj server, it is easy to set up fast IPC between bashj scripts.
The following u methods allow to set() and get() inter process variables:
public static String get(String key,boolean scriptSpecific,boolean persist)
public static String get(String key)
The scriptSpecific flag indicates whether this value is shared or not with other scripts. These values will be kept during successive calls of the calling scripts, until the server is stopped.
The persist flag indicates whether the values should persist in the host file system. These values will be saved when the server is stopped.
The simple calls (without boolean parameters) assume scriptSpecific is true, persist is false.
Script coding examples
Here are some basic examples, extracted from the wider list of examples provided as part of the installation process (example subdir).
#!/usr/bin/bashj
#!java
static int factorial(int n)
{if (n<=0) return(0);
if (n==1) return(1);
return(n*factorial(n-1));}
#!bashj
echo j.factorial(10)
#!/usr/bin/bashj
#!java
static void main()
{u.p("Hello, bashj world !");
u.p("This code is executed in a JVM "+System.getProperty("java.version"));
u.p("But it is processed through bashj and finally bash");}
#!/usr/bin/bashj
echo Math.cos(0.5)
echo Math.hypot(3.0,4.0)
echo System.getProperty("java.runtime.version")
#!/usr/bin/bashj
#!java
static String ax2_bx_c(double a,double b,double c)
{final double r=b*b-4*a*c;
if (r<0.0) return("NoRoot");
if (r==0.0) return(""+(-b/(a+a)));
final double sq=Math.sqrt(r);
return(""+(-b-sq)/(a+a)+" "+(-b+sq)/(a+a));}
#!bashj
echo "... Delivers the roots of a quadratic equation"
A=1.0
B=-5.0
C=6.0
echo "... Solving $A X^2 + $B X + $C"
echo "... Roots are " j.ax2_bx_c($A,$B,$C)
#!/usr/bin/bashj
echo "bashj server utilities"
echo
server.classes()
echo
server.methods("bashj.u.")
echo
server.fields("ersion")
echo
server.info()
#!/usr/bin/bashj
echo "bashj string utilities"
echo
WORD=Bonjour
echo length of $WORD is u.strlen($WORD)
LETTER=u
echo index of $LETTER in $WORD is u.indexOf($WORD,$LETTER)
echo Uppercase u.toUpperCase($WORD)
echo Lowercase u.toLowerCase($WORD)