What's GSMLWorkshop?

GSML(Grid Service Markup Language)Workshop is an agile integration tool for Grid applications,which consists of three parts: GSML Language, GSML Composer and GSML Browser.GSML Language is a XML-based programming language for end-users to build Grid applications on-demand. GSML Language enables flexible application logic and collaboration mechanisms by reusable funnels with event-based models. Cored on GSML, GSML Workshop provides a visual integrated developing environment for developers to edit, debug and run the applications intuitively and quickly. With it, the developers build and refractor the applications by assembling reusable,event-based components. Compared with the application development using API in high-level languages,GSML Workshop enhances the productivity of Grid Application development.
GSML Workbench features
  • Reusable components. Aiming to enable agile development and deployment Grid Application,GSML Workshop provides a library of highly reusable components which support the mainstream Grid middlewares such as Globus Toolkit, OMII and CNGrid GOS. Developers with GSML Workshop need not to recreate all the common modules of application from the scratch, instead they can build the applications quickly by reusing the components in the library. In this way, GSML Workshop presents higher software reusabilities and development effectiveness.

  • Event-driven programming model. With GSML, the flexible logic and collaboration of Grid Applications are specified in the event-driven fashion. The connection mechanism of GSML runtime system is implemented as an event bus. It enables users to program the interactions between software components and grid resources in a uniform, asynchronous event communication method, which effectively and flexibly supports complex patterns of Grid Applications, such as workflows and interactive applications.
  • WYSIWYG programming environment. By providing a visual WYSIWYG integrated development environment, the users who build Grid Application are not required to enjoy extensive programming knowledge. To program, the users drag the component from the library and drop into the GSML pages, customize its property and behaviors. The users are also able to intuitively see the runtime effects, debug and trace the execution at the same time. The only requirement of users is the configuration, and the whole development process requires none or little coding. Therefore for the developers, GSML Workshop lowers the knowledge barrier, shortens the development schedules and cuts down the cost as well.

Requirements

  • Software
    • OS: Windows 2K & XP
    • JDK: >1.4
  • Hardware
    • Minimum Memory: 512M

Install GSMLWorkshop

  • Download the GSMLWorkshop compressed binary package(gsml_bin)from the website(http://sourceforge.net/project/showfiles.php?group_id=125126).
  • Unpack the compressed package with utility such as WinZip or 7-Zip.
  • Download the funnel_bin package from the website(http://sourceforge.net/project/showfiles.php?group_id=125126)
  • Unpack the compressed package with Winzip or 7-Zip to <GSMLWorkshop_Dir>/funnels
  • Edit the environment variable PATH to contain the location of JRE(Java Runtime Environment).
  • Launch GSMLWorkshop by clicking the executable file eclipse.exe under the uncompressed package directory, and select the component to start the exploration with GSMLWorkshop.

Build the GSMLWorkshop Source Code

The GSMLWorkshop source code is developed and tested with Eclipse 3.2. The following steps are required to install and build the source code.
  • Download the GSMLWorkshop source package from the website.
  • Unpack the source packages with utility such as WinZip or 7-Zip.
  • Download the funnel_bin package from the website(http://sourceforge.net/project/showfiles.php?group_id=125126)
  • Unpack the compressed package with Winzip or 7-Zip to <GSMLWorkshop_Src_Dir>/funnels
  • In Eclipse development environment, import the unpacked source project

  • Copy two plugins, org.apache.activemq and org.ict.gsml.thirdparty_1.0.0 from the source project's misc directory to the directory eclipse3.2_install_dir>/plugins/.

  • Restart the Eclipse development environment, and build the project GSMLWorkshop
  • Run the project as Eclipse Application with the following setting

Use GSML Composer

To startGSML Composer, click the eclipse in the unzipped GSMLWorkshop directory, select the GSML Composer when the components selection dialog displays.


Click the OK button to continue, then the GSML Composer is launched.


There is a new page open in GSML Composer,users can open existing pages and new another page from the menu or toolbar.


For each page,there are four views for the pages, three of them corresponds to the LayoutView,FunnelLogic,SessionLogic views, and another one is the code view of the GSML page.

The installed funnels are listed according to the catalogs of the funnel on the left panel.To manage the catalogs,expand the Funnel Repository Manager item, where some catalogs can be hidden,and new funnels can be updated.


To add funnels to GSML page, drag the items from the catalogs in the Funnel Repository and drop it into the page views except the code view.
  • In the Layout view, visible funnels are showed as they were in GSML Composer,and invisible funnels are showed as their icons on the right side of the view.


  • FunnelLogic View displays the funnels and the interactions between them in the funnel based so the interactions of a single funnel can be viewed by checking the connections connected from or to the funnel.


  • SessionLogic View displays the page's definition of sessions. A session contains a connected graph nodes and links in the same color. This view is organized by sessions, while the FunnelLogic is by Funnel.


The properties page of the composer enables user to change the property of funnels and setting the details of connections.
An example of setting properties of funnel MSExcel is as following,


The following example show how to set the properties of the connection setValue of funnel MSExcel.


The properties of funnels are always edited directly by clicking the value entry of the settable item, while most of the properties of connections should be edited by clicking the button on the right end of the property's value entry and editing the value in the connection properties dialog box.For example, the following is to edit the value parameter of event setValue for the funnel MSExcel.


Showed in the above picture, values of the connection properties can be combination of properties of other funnels, event context causally related to this connection, Options. Moreover, to set complex logic for the property value, users can click the button Use Javascript to enable javascript code in the value.


To validate the javascript, users can click the button Validate Javascript to check if the script is OK.


When a GSML application's funnels and their interactions are composed in the Composer,save the page in a GSML document. The saved code can be viewed in the code view of GSML Composer.


Now to run the GSML application,you can click the Run menu item or the toolbar item.


In the Preference setting page of GSML Composer, two important configuration items can be changed. One is the URL of funnel update site, another is address of the Event service.


The funnel update site is a site for users to upload and download the funnels,where users can share the funnel components with each other. To access the update site, please click the button Update in the Funnel Repository Page on GSML Composer's left panel.

The event service address sets where the communication infrastructure between funnels and the session manager locates. Currently the infrastructure is based on ActiveMQ, and the address is in the form vm://localhost or tcp://192.168.1.56.Please make sure the address is correct before running the GSML applications in GSML browser.

Use GSML Browser


There are two ways to launch GSML Browser:one is to select GSML Composer in the GSML Workshop's Component selection dialog, and another is to launch the Run action from the GSML Composer's menu or toolbar.When the Browser is started, the screenshot is as below.


Other GSML applications can be loaded into GSML Browser by the menu Open or directly inputing the address of the gsml document in the address bar.

Actually, the address of the GSML documenet can be any URL,e.g., ftp://test:test@192.168.1.56/incoming/test.gsml or http://192.168.1.56/test.gsml

To update the gsml document being edited by GSML Composer, save the document in the Composer,and launch the Refresh action of the Browser. This will stop and free the previously loaded application,and reload the newly saved GSML document again.


Develop a funnel

A funnel is a software component in GSMLWorkshop and it is the only building block in GSML applications. When a new resource is required to be included in an application, a new funnel is developed to encapsulate the resource access interfaces. Roughly, funnels can be categorized into two classes: GUI funnels (Visible funnels) and NonGUI funnels (Invisible funnels).

Download the example source code

The source code of the examples in the following sub-sections are available on the website. To test the example codes, follow the steps below:
  • Download the source package
  • Unpack the source package with compress utility such as WinZip or 7-Zip.
  • Import the source projects from the unpacked directory to Eclipse development environment
  • To build the funnels, run the ant build files funnelbuild.xml of the projects.
  • When the building finishes, the funnel is located under <funnel_project>/packed.
  • To test a funnel, copy the generated funnel directory under<funnel_project>/packed to the directory <GSMLWorkshop_bin_dir>/funnels or<GSMLWorkshop_project_dir>/funnels.
  • To check and use the generated funnels, restart the GSMLWorkshop and load the gsml files nonguifunneltest.gsml and guifunneltest.gsml under the unpacked source directory.

Develop a GUI funnel

Here an example is used to illustrate how to turn a GUI application into a funnel in GSMLWorkshop. The GUI application is the one that shows the usage of SWT tree component. When the application is encapsulated into a funnel, it has the same gui appearence and behavior as the original application.


GUI Application code

import org.eclipse.swt.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

/**
 * Displays a single-selection tree, a multiselection tree, and a checkbox tree
 */
public class TreeExample {
	/**
	 * Runs the application
	 */
	public void run() {
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setText("TreeExample");
		createContents(shell);
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
		display.dispose();
	}

	private void createContents(Composite composite) {
		// Set the single-selection tree in the upper left,
		// the multiselection tree in the upper right,
		// and the checkbox tree across the bottom.
		// To do this, create a 1x2 grid, and in the top
		// cell, a 2x1 grid.
		composite.setLayout(new GridLayout(1, true));
		Composite top = new Composite(composite, SWT.NONE);
		GridData data = new GridData(GridData.FILL_BOTH);
		top.setLayoutData(data);

		top.setLayout(new GridLayout(2, true));
		Tree single = new Tree(top, SWT.SINGLE | SWT.BORDER);
		data = new GridData(GridData.FILL_BOTH);
		single.setLayoutData(data);
		fillTree(single);

		Tree multi = new Tree(top, SWT.MULTI | SWT.BORDER);
		data = new GridData(GridData.FILL_BOTH);
		multi.setLayoutData(data);
		fillTree(multi);

		Tree check = new Tree(composite, SWT.CHECK | SWT.BORDER);
		data = new GridData(GridData.FILL_BOTH);
		check.setLayoutData(data);
		fillTree(check);
	}

	/**
	 * Helper method to fill a tree with data
	 *
	 * @param tree the tree to fill
	 */
	private void fillTree(Tree tree) {
		// Turn off drawing to avoid flicker
		tree.setRedraw(false);

		// Create five root items
		for (int i = 0; i < 5; i++) {
			TreeItem item = new TreeItem(tree, SWT.NONE);
			item.setText("Root Item " + i);

			// Create three children below the root
			for (int j = 0; j < 3; j++) {
				TreeItem child = new TreeItem(item, SWT.NONE);
				child.setText("Child Item " + i + " - " + j);

				// Create three grandchildren under the child
				for (int k = 0; k < 3; k++) {
					TreeItem grandChild = new TreeItem(child, SWT.NONE);
					grandChild.setText("Grandchild Item " + i + " - " + j
							+ " - " + k);
				}
			}
		}
		// Turn drawing back on!
		tree.setRedraw(true);
	}

	/**
	 * The entry point for the application
	 *
	 * @param args the command line arguments
	 */
	public static void main(String[] args) {
		new TreeExample().run();
	}
}


Make a GUI funnel

To turn the GUI application into a funnel, some files (or directories) are required to add to the projects
  • funnel.xml, a specification file which states the author, jar file requirements, the type, catalog and the implementation class files of the built funnel
  • funnelib, a directory contains two jar files,pipebase.jar and funnelbase.jar needed, which required by the implementation of the funnel.
  • funnelbuild.xml, ant build file to build the funnel
  • icons, a directory contains the icon files used by the funnel.
  • lib, a directory contains the jar files required by the funnel
  • a funnel implementation file, which implements the funnel interfaces.
The funnel implementation file define a java class inherited base class VisualFunnel.
import org.eclipse.swt.widgets.Composite;
import org.ict.gsml.funnels.base.VisualFunnel;


public class TreeExampleFunnel extends VisualFunnel{

	TreeExample ui;
	public TreeExampleFunnel(Composite parent, String pageID, String pipeID,
			String host, int port) {
		super(parent, pageID, pipeID, host, port);
	}
	
        /**
          * Dispose the resources allocated by the funnel.
          */  
	public void unLoad() {
		ui.dispose();
		super.unLoad();
	}
	
        /**
         * Init the things in postinit(), so that they can use 
         * the initialized interfaces such as funnel properties,
         * event definitions
         */ 
	public void postinit(){
		ui = new TreeExample();
		ui.init(getParentPanel(),this);
	}
}

What's more , some modification is needed in order that the functions of the GUI application can be called in the funnel implementation file.
/**
 * Displays a single-selection tree, a multiselection tree, and a checkbox tree
 */
public class TreeExample {
	/**
	 * Runs the application
	 */
	public void run() {
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setText("TreeExample");
		createContents(shell);
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
		display.dispose();
	}

	private void createContents(Composite composite) {
		// Set the single-selection tree in the upper left,
		// the multiselection tree in the upper right,
		// and the checkbox tree across the bottom.
		// To do this, create a 1x2 grid, and in the top
		// cell, a 2x1 grid.
		composite.setLayout(new GridLayout(1, true));
		Composite top = new Composite(composite, SWT.NONE);
		GridData data = new GridData(GridData.FILL_BOTH);
		top.setLayoutData(data);

		top.setLayout(new GridLayout(2, true));
		Tree single = new Tree(top, SWT.SINGLE | SWT.BORDER);
		data = new GridData(GridData.FILL_BOTH);
		single.setLayoutData(data);
		fillTree(single);

		Tree multi = new Tree(top, SWT.MULTI | SWT.BORDER);
		data = new GridData(GridData.FILL_BOTH);
		multi.setLayoutData(data);
		fillTree(multi);

		Tree check = new Tree(composite, SWT.CHECK | SWT.BORDER);
		data = new GridData(GridData.FILL_BOTH);
		check.setLayoutData(data);
		fillTree(check);
	}

	/**
	 * Helper method to fill a tree with data
	 *
	 * @param tree the tree to fill
	 */
	private void fillTree(Tree tree) {
		// Turn off drawing to avoid flicker
		tree.setRedraw(false);

		// Create five root items
		for (int i = 0; i < 5; i++) {
			TreeItem item = new TreeItem(tree, SWT.NONE);
			item.setText("Root Item " + i);

			// Create three children below the root
			for (int j = 0; j < 3; j++) {
				TreeItem child = new TreeItem(item, SWT.NONE);
				child.setText("Child Item " + i + " - " + j);

				// Create three grandchildren under the child
				for (int k = 0; k < 3; k++) {
					TreeItem grandChild = new TreeItem(child, SWT.NONE);
					grandChild.setText("Grandchild Item " + i + " - " + j
							+ " - " + k);
				}
			}
		}
		// Turn drawing back on!
		tree.setRedraw(true);
	}

	/**
	 * The entry point for the application
	 *
	 * @param args the command line arguments
	 */
	public static void main(String[] args) {
		new TreeExample().run();
	}

	/*************************************************************
	 * 
	 * Added for funnel encapsulation
	 * 
	 *************************************************************/
	
	TreeExampleFunnel funnel;
	/**
	 * init
	 * 
	 * Initialize the UI
	 * 
	 * @param parentPanel
	 * @param funnel
	 */
	public void init(Composite parentPanel, TreeExampleFunnel funnel) {
		this.funnel = funnel;
		createContents(parentPanel);
		parentPanel.layout();
	}

	/**
	 * Dispose the resource allocate by the funnel  
	 *
	 */
	public void dispose() {
		
	}	
}

The funnel specification file funnel.xml is list as below:
<?xml version="1.0" encoding="UTF-8"?>
<?GSMLBrowser version="1.0"?>
<funnels xmlns="http://gsml.ict.org" xmlns:xsi="http:/
/www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://gsml.ict.org pipe.xsd"
	provider="ict">
	
	<requires>
	</requires>
    <!-- 
       Define the jar files required by runtime to load the funnel
       It includes the funnel implementation class and other jar files
       the implmentation depends upon
    -->
	<runtime>
	 <library type="archive" location="GUIFunnelExample.jar"/>

	</runtime>
	<description>GUIFunnel Example</description>
    <!-- 
        Each funnel element specifies a funnel implmentation. Multiple
        funnels can be implemented in a single file.
    	catalog specifies the catalog of the funnel 
    	type specifies the type of the funnel
    	class specifies which class in the implementation jar has 
    	 implements the funnel interface
    	icon specifies the icon representing the funnel in GSMLComposer 
    -->
    <funnel catalog="FunnelExample" type="GUIFunnelExample" class="
	TreeExampleFunnel" 
	  	version="1.0.0" icon="icons/funnel.jpg">	  	
	  	<description>Funnel Example</description>

	</funnel>
</funnels>

tt> The ant build file funnelbuild.xml is required to build and package the funnel.
<?xml version="1.0" encoding=
"UTF-8"?>
<!DOCTYPE project [<!ENTITY buildfile SYSTEM "file:./build-user.xml
">]>
<!-- WARNING: Eclipse autogenerated file. 
              Any modifications will be overwritten.
              Please edit build-user.xml instead.
-->

<!--
 The project name will affect the jar file name of funnel implementation.
-->
<!-- change here:project name="XXXX" -->
<project name="GUIFunnelExample" default="build" basedir=".">
	<property name="top.dir" value="." />
	<property name="bin.dir" value="${top.dir}/bin" />
	<property name="packed.dir" value="${top.dir}/packed" />
    <path id="project.classpath">

        <pathelement location="${bin.dir}/${ant.project.name}"/>
    	<!-- 
    	 Each fileset defines a directory of jar files that
    	 needed to build the funnel
    	-->
    	<fileset dir="${top.dir}/lib">
      		<include name="*.jar" /> 
      	</fileset>
    	<fileset dir="${top.dir}/funnellib">

      		<include name="*.jar" /> 
      	</fileset>
    </path>
    <target name="init">
    	<mkdir dir="${packed.dir}/${ant.project.name}"/>
        <mkdir dir="${bin.dir}/${ant.project.name}"/>

    </target>
    <target name="clean">
        <delete dir="${top.dir}/${ant.project.name}"/>
    </target>
    <target name="build" depends="init">
        <echo message="${ant.project.name}: ${ant.file}"/>

        <javac destdir="${bin.dir}/${ant.project.name}"         	
			target="1.4" 
        	source="1.4"
        	debug ="true">
            <src path="."/>
            <classpath refid="project.classpath"/>
        </javac>
    	<jar jarfile="${packed.dir}/${ant.project.name}/${ant.project.n
		ame}.jar" >
    		<fileset dir="${bin.dir}/${ant.project.name}"/>

    	</jar>
    	<copy file="funnel.xml" toDir="${packed.dir}/${ant.project.name}/" 
		/>
    	<mkdir dir="${packed.dir}/${ant.project.name}/icons"/>
    	<copy todir="${packed.dir}/${ant.project.name}/icons">
    	    <fileset dir="icons" includes="**/*.*"/>
    	</copy>

    	<copy todir="${packed.dir}/${ant.project.name}/">
    	    <fileset dir="lib" includes="**/*.*"/>
    	</copy>
    </target>
</project>


To test the funnel, copy the generated funnel directory packed/GUIFunnelExample into directory <GSMLWorkshop_src>/funnels or <GSMLWorkshop_bin>/funnels, and load the guifunneltest.gsml into the GSMLComposer.

Develop a NonGUI funnel

A NonGUI funnel is a software module without GUI. In this example, a module that converts a xml file into a html page using XSLT is encapsulated into a funnel.
An application illustrating the module is defined in file XML2HTML.java
package org.ict.gsml.funnels;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;

import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

public class XML2HTML {
	private static File getFileFromString(String filename){
		File file = null;
		
		try {
			URL fileurl;
			fileurl = new URL(filename);
			file = new File(fileurl.toURI());
			return file;
		} catch (MalformedURLException e) {
			
		} catch (URISyntaxException e) {
			
		}
		
		file = new File(filename);
		
		return file;
	}
	
	public static String xml2htmlTrans(String xmlFileName, String xsltFileName) {
		String htmlFileName = null;

		File xmlFile = getFileFromString(xmlFileName);
		File xsltFile = getFileFromString(xsltFileName);
		if(xmlFile == null || xsltFile == null)
			return "error";
		String path = xmlFile.getAbsolutePath();
		htmlFileName = path.substring(0, path.length() - 4);
		File htmlFile = new File(htmlFileName + ".html");

		// JAXP reads data using the Source interface
		Source xmlSource = new StreamSource(xmlFile);
		Source xsltSource = new StreamSource(xsltFile);

		// the factory pattern supports different XSLT processors
		TransformerFactory transFact = TransformerFactory.newInstance();

		try {
			Transformer trans = transFact.newTransformer(xsltSource);
			trans.transform(xmlSource, new StreamResult(htmlFile));
		} catch (javax.xml.transform.TransformerException tfe) {
			System.out.println(tfe.getMessage());
			return "error";
		}

		return htmlFileName + ".html";
	}
	public static void main(String[] args) {
		String filename = null;
		filename = XML2HTML.xml2htmlTrans("footballteam.xml",
				"footballteam.xsl");
		System.out.println(filename);
	}
}

Add the required files and directories to the source project, and add a funnel implementation file XML2HTMLEngineFunnel.java. The function buildEventTemplates() defines the event templates that the funnel has, and the function buildEventHandlers() defines the event handlers for each input event templates defined in function buildEventTemplates().

package org.ict.gsml.funnels;

/*
 * Created on 2006-07-14
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */

import org.eclipse.swt.widgets.Composite;
import org.ict.gsml.core.event.Event;
import org.ict.gsml.funnels.base.BaseFunnel;
import org.ict.gsml.funnels.base.EventHandler;
import org.ict.gsml.funnels.base.InEventTemplate;
import org.ict.gsml.funnels.base.OutEventTemplate;
import org.ict.gsml.funnels.base.OutputEvent;

/**
 * TODO: FireAtDate and FireAtPeriod should be set to associate with the
 * TimerAtPeriod and TimerAtDate in the file
 */
/**
 * @author Administrator
 * 
 * TODO To change the template for this generated type comment go to Window -
 * Preferences - Java - Code Style - Code Templates
 */
public class XML2HTMLEngineFunnel extends BaseFunnel {

	/**
	 * 
	 */

	public XML2HTMLEngineFunnel(Composite parent, String pageID, String pipeID,
			String host, int port) {
		super(parent, pageID, pipeID, host, port);
	}

	protected void init() {

	}

	protected void setDefaultProperties() {

	}

	protected void buildEventTemplates() {
		super.buildEventTemplates();

		// InEventTemplate
		addEventTemplate(new InEventTemplate("Execute", new String[] {
				"xmlFileName", "xslFileName" }));

		// OutEventTemplate
		addEventTemplate(new OutEventTemplate("Error", new String[] { "msg" }));
		addEventTemplate(new OutEventTemplate("result", new String[] { "res" }));
	}

	protected void buildEventHandlers() {
		super.buildEventHandlers();

		EventHandler execute = new EventHandler(this, "Execute", new String[] {
				"Error", "result" }) {
			public OutputEvent[] handleEvent(Event arg0) {
				String xmlFileName = getStringPara("xmlFileName", null);
				String xslFileName = getStringPara("xslFileName", null);

				String resStr = null;
				try {
					resStr = XML2HTML.xml2htmlTrans(xmlFileName, xslFileName);

				} catch (Exception e) {
					OutputEvent error = XML2HTMLEngineFunnel.this
							.createOutEvent("Error");
					error.setPara("msg", "XML2HTMLEngine error: "
							+ e.getMessage());
					return new OutputEvent[] { error };
				}

				OutputEvent result = XML2HTMLEngineFunnel.this
						.createOutEvent("result");
				result.setPara("res", resStr);
				return new OutputEvent[] { result };
			}
		};

		addEventHandler(execute);
	}
}

Its specification file funnel.xml is as following
<?xml version="1.0"
 encoding="UTF-8"?>
<?GSMLBrowser version="1.0"?>
<funnels xmlns="http://gsml.ict.org" xmlns:xsi="http://www.w3
.org/2001/XMLSchema-instance" xsi:schemaLocation="http://gsml.ict.org pipe.xsd"
	provider="ict">
	
	<requires>
	</requires>
 
	<runtime>
	 <library type="archive" location="NonGUIFunnelExample.jar"/>

	 <!--<library type="archive" location="otherdep.jar"/>-->
	</runtime>
	<description>NonGUI Funnel Example</description>

    <funnel catalog="FunnelExample" type="NonGUIFunnelExample" class="
	org.ict.gsml.funnels.XML2HTMLEngineFunnel" 
	  	version="1.0.0" icon="icons/xml2html.jpg">	  	
	  	<description>XML2HTML Engine Funnel</description>

	</funnel>
</funnels>

The ant build file is specified in funnelbuild.xml
<?xml version="1.0" encoding="UTF-8"
?>
<!DOCTYPE project [<!ENTITY buildfile SYSTEM "file:./build-user.xml">
;]>
<!-- WARNING: Eclipse autogenerated file. 
              Any modifications will be overwritten.
              Please edit build-user.xml instead.
-->
<!-- change here:project name="XXXX" -->

<project name="NonGUIFunnelExample" default="build" basedir=".">
	<property name="top.dir" value="." />
	<property name="bin.dir" value="${top.dir}/bin" />
	<property name="packed.dir" value="${top.dir}/packed" />
    <path id="project.classpath">
        <pathelement location="${bin.dir}/${ant.project.name}"/>

    	<fileset dir="${top.dir}/lib">
      		<include name="*.jar" /> 
      	</fileset>
    	<fileset dir="${top.dir}/funnellib">
      		<include name="*.jar" /> 
      	</fileset>
    </path>

    <target name="init">
    	<mkdir dir="${packed.dir}/${ant.project.name}"/>
        <mkdir dir="${bin.dir}/${ant.project.name}"/>
    </target>
    <target name="clean">
        <delete dir="${top.dir}/${ant.project.name}"/>

    </target>
    <target name="build" depends="init">
        <echo message="${ant.project.name}: ${ant.file}"/>
        <javac destdir="${bin.dir}/${ant.project.name}"         	
			target="1.4" 
        	source="1.4"
        	debug ="true">
            <src path="."/>
            <classpath refid="project.classpath"/>

        </javac>
    	<!-- otherthings to jar -->
    	<jar jarfile="${packed.dir}/${ant.project.name}/${ant.project.
		name}.jar" >
    		<fileset dir="${bin.dir}/${ant.project.name}"/>
    		<!--<fileset dir="..\Controls">
    			<include name="**/icons/**"/>

    		</fileset> -->
    	</jar>
    	<copy file="funnel.xml" toDir="${packed.dir}/${ant.project.name}/" />
    	<mkdir dir="${packed.dir}/${ant.project.name}/icons"/>
    	<copy todir="${packed.dir}/${ant.project.name}/icons">

    	    <fileset dir="icons" includes="**/*.*"/>
    	</copy>
    </target>
</project>

To test the funnel, copy the generated funnel directory packed/NonGUIFunnelExample into directory <GSMLWorkshop_src>/funnels or <GSMLWorkshop_bin>/funnels, and load the guifunneltest.gsml into the GSMLComposer.