1. Introduction

1.1 The design

The code section below shows how the jxp processor works:

//first of all, declare a page source
FilePageSource pageSource = new FilePageSource("/home/joe/jxp");

//then declare a jxp context which encapsulate the processing environment for jxp (including the page source)
//optionally, you can also use JxpContext(JxpPageSource pageSource, Map defaultEnv) which will pass in a default
//environment that is will be available to all the pages you are processing using the context
JxpContext context = new JxpContext(pageSource);

//declare the processor and make it use the context
JxpProcessor processor = new JxpProcessor(context);

//now, you can start process pages
Writer writer = new OutputStreamWriter(System.output);
processor.process("test.jxp", writer); //this will process page "/home/joe/jxp/test.jxp"
writer.flush();

//you can also process another page with some given initial environment (which become variables in your page)
Map env = new HashMap();
env.put("ONE", new Integer(1));
//start processing
processor.process("/test2.jxp", writer, env); //you can refer "ONE" as a variable in your script
                
Several comments on the code segment above:
  • FilePageSource is a JxpPageSource. It is instantiated to be used by the processor for loading JxpPages from the given directory "/home/joe/jxp". Other implementation of JxpPageSource include ResourceStreamPageSource which load scripts from class path resources (using Class.getResourceAsStream()) and MultiSourcePageSource which is a composite JxpPageSource. The MultiSourcePageSource can aggregate several JxpPageSource to form a single JxpPageSource. Both FilePageSource and ResourceStreamPageSource support caching of parsed syntax tree.
  • Only one instance of the JxpProcessor is needed for processing multiple jxp scripts since the JxpProcessingContext is used to identify the current processing environment of the script. Even in multi-threaded environment, only one processor per web context is needed, assuming each web context need to use different page source.
  • The JxpProcessingContext is used to identify the current environment and the output writer of the processing of a script.

2. Using the processor

The different ways of using the jxp script processor is explain in the quick start guide. This section describe how to use xml config to describe a processing environment and use JxpFactory create the jxp processor from the xml.

2.1 Using xml config and JxpFactory

While it is not required, it is possible to describe the jxp processing environment using an xml file.

<?xml version='1.0' encoding='UTF-8'?>
<jxp>
	<!-- the environment -->
	<env>
		<var name="intvalue" type="int" value="1"/>
		<var name="defaultvalue" value="default"/>
		<var name="shortvalue" type="short" value="1"/>
		<var name="intvalue" type="int" value="1"/>
		<var name="longvalue" type="long" value="1"/>
		<var name="floatvalue" type="float" value="1"/>
		<var name="doublevalue" type="double" value="1"/>
		<var name="charvalue" type="char" value="c"/>
		<var name="stringvalue" type="string" value="string"/>
	</env>
    <!-- the page source -->
	<pagesources>
        <!-- a MultiSourcePageSource -->
		<multisource>
            <!-- a FilePageSource, with caching on -->
			<filesource path="/" caching="true"/>
            <!-- the ResourceStreamPageSource, with caching off -->
			<streamsource path="/" caching="false"/>
		</multisource>		
	</pagesources>
</jxp>
                
Subsequently, the JxpFactory is used to create a processor out of the jxp environment
JxpProcessor processor = JxpFactory.getProcessor(new FileInputStream("jxp.xml"));
//... move on                    
                
The environment section is a way allow some common variables (e.g. configuration variables) that can be shared and used throughout the scripts. As you can see, the environment support creating different types (primitive or non-primitive) of property as the default environment in your JxpContext.

3. Language feature support

The script supports most of the java constructs but there are several differences/limitations. The following subsections clarify these.

3.1 The script syntax

The script file contains the text and java code section that the JxpProcessor will execute. By default the script is in text mode and the processor will print everything in the text mode. The java mode is started with the "<%" tag. The processor will execute any java code in java mode. The script goes back to text mode again with the "%>" tag.

Also, the "<%=var%> allows the user to print the value of the variable var in the text mode. Alternatively, the back-quote can be used (e.g. `var`). The following example shows the syntax

This is normal text
This is text with variable <%=var1%>
This is another text with variable `var1`
<%
    import java.util.*;    
    //java statements go here   ...     
%>            
            


Since jxp 1.5, there's a new syntax <%!! .... !!%> which can allow the user to bypass parsing and just print the content between the tags to output. It will be useful for example to generate jsp text. For example, instead of
              <%
                println("<% ... my generated content jsp ... %>");
              %>
            
you can write
              
              <%!!
                <%
                  ... my generated jxp content ...
                %>
              !!%>
            
Since jxp 1.5.2, JSP page and include directive are supported in the syntax, but has no effect on the script output except for the import directive.

3.2 Jxp special functions

Jxp provide some special functions and environments that can be use anywhere in your jxp script

functiondescriptionexample
println(String string); println(Object obj); Print the string/obj to the output println("this is a test");
include(String scriptname); Include another script in current script. if script name starts with "/" it identify a script in the page source. otherwise the scriptname is resolved relative in the current JxpPage.
//supposed current page is "/jxp-script/test.jxp", 

include("included.jxp"); //will include "/jxp-script/included.jxp"  
include("/included.jxp"); //will include "/included.jxp" 
function It is for defining function. (since jxp 1.0.0-beta)
 function void theFunction(String message){
     //do something
 }
 
 theFunction("test"); //call it
                     
exit exit the script no matter how deep the include level are exit;
getJxpEnvironment() Get all the variables defined in the scope at the point of execution println(getJxpEnvironment()); //print the environment
environmentdescription
jxp_writer the writer jxp use to writes output
jxp_script_name the current script name
jxp_context the current processing context (deprecated as in 1.3.0)
The following environment only applies to jxp file in web-scripts environment
form (only when used as web-script) the posted web form when used as web-script. it supports file upload and if the field of upload file is "file1", it will generate these variables:

file1.ITEM = the DefaultFileItem (see javadoc)

file1.CONTENT_TYPE = the content type of the file

file1.FILENAME = the original file name of uploaded file
req the servlet request
resp the servlet response

3.3 Java language support

java featuresupportednote
import statement yes Your can place import statement anywhere in your script file as long as it is before the use of the classes in that package. You can import the same package more than once.
field declaration 99% 1. Jxp does not do type checking in declaration for performance reason

2. Before 1.3.0, static means nothing in jxp. After 1.3.0, static means that a variable is static to the page. The value of the variable remains over the lifetime of a specific page (In FilePageSource, the page static variable is purged when the file modification is detected and reload from file system)
operators 99% 1. casting is not implemented (since jxp is not designed to be strong-typed script language)
control flows 99% 2. Label/goto statement will not be implemented
class definition and method definition no 1. Class definition is not implemented since jxp is used for scripting

2. Method definition will be implemented as function definition for scripts (see description below)
try...catch... yes
synchronized yes
assertion yes
method declaration yes (since jxp 1.0.0-beta) Instead of using normal "public void functionName(...)", use "function void functionName(...)" to declare a function. Also, The name of function should be unique per-page (per-processing actually). Before 1.3.0, function cannot access global variable but since 1.3.0, they could.
enhanced for loop yes (since jxp 1.1.0) Example:

for (Object a: intList){ System.out.println(a); }
static import yes (since jxp 1.1.0) static import will import static variables and methods into the script scope.
var args * partial (since jxp 1.1.0). The feature allows definition of variable arguments function in the script. Invocation of varargs in jdk 1.5 will be implemented in jxp 2.0.

3.4 JSP constructs supported

JXP didn't started out as JSP parser but it was suggested that it will be more useful as JSP-compatible. For JPS 2.0 syntax reference link is here Not all JSP feature are implemented yet in JXP but here are some JSP constructs that JXP recognizes.

jsp featuresupportednote
comment yes Example:
	<%-- comment --%> 
field declaration 99% Example:
	<%! int i = 0; %>	 
OR
	<jsp:declaration>int i = 0;</jsp:declaration>
1. Jxp does not do type checking in declaration for performance reason

2. Before 1.3.0, static means nothing in jxp. After 1.3.0, static means that a variable is static to the page. The value of the variable remains over the lifetime of a specific page (In FilePageSource, the page static variable is purged when the file modification is detected and reload from file system)
Expression yes Example:
	<%=var1%>	 
OR
	<jsp:expression>var1</jsp:expression>
import directive yes This is only attribute supported in page directive Example:
scriptlet yes While natively JXP already recognizes the
	<%...%>	 
, it also takes
  <jsp:scriptlet>	code fragment  </jsp:scriptlet>  
Expression language 99% All operations are supported except Function invocation. Example:
  ${"Test=" + test} 

4. Java scripting in ant

4.1 The ant task

To use jxp as ant task, just place all the jars in the jxp distribution in classpath, and use the following code


  <target name="test1">
    <typedef name="jxp" classname="org.onemind.jxp.ant.JxpAntTask"/>
    <jxp scriptpath="myscripts">
      println("testing");
      for (int i=0; i<10; i++){
        println("test " + i);
      }
      println(getJxpEnvironment());
      include ("abc.jxp"); //include another jxp script       
    </jxp>
  </target>

          
For most code, you might want to put the code section in <![[CDATA .... ]]> section to avoid xml parse error. The scriptpath property defines the path to other jxp scripts that you want to include. If omitted, the current dir will be used as the script path. Several environment variables are defined in the scope of the script section:
          project --> the ant project of this task
          location -> the location of this task
          description --> the description of this task
          target --> the target name 
          taskname --> the taskname (jxp)
          
So you can use these environment objects as you see fits. All the other environments from project.getProperties() are also in scope. Unfortunately, in ant/java world a lot of variable are dotted (e.g. ant.home). So to access these variables, you can one of the following in your script:
            String antHome = project.getProperties().get("ant.home"); //get property from project
            String antHome = getJxpEnvironment().get("ant.home"); //get from jxp global environments
          
This should provide enough information about the jxp/java scripting in ant. Use forum to post any concern/issues you have.