Adding new website from r3934 JABA_r1 branch
authorpvtroshin <pvtroshin@e3abac25-378b-4346-85de-24260fe3988d>
Fri, 8 Apr 2011 12:35:44 +0000 (12:35 +0000)
committerpvtroshin <pvtroshin@e3abac25-378b-4346-85de-24260fe3988d>
Fri, 8 Apr 2011 12:35:44 +0000 (12:35 +0000)
git-svn-id: link to svn.lifesci.dundee.ac.uk/svn/barton/ptroshin/JABA2@3936 e3abac25-378b-4346-85de-24260fe3988d

41 files changed:
website/Example_template.pdf [new file with mode: 0644]
website/contacts.html [new file with mode: 0644]
website/develhome.html [new file with mode: 0644]
website/download.html [new file with mode: 0644]
website/images/VMware_booted.png [new file with mode: 0644]
website/images/VMware_copy_q.png [new file with mode: 0644]
website/images/VMware_cpu.png [new file with mode: 0644]
website/images/align.png [new file with mode: 0644]
website/images/banner_bg.gif [new file with mode: 0644]
website/images/banner_bg1.gif [new file with mode: 0644]
website/images/brickhead2.jpg [new file with mode: 0644]
website/images/brickhead2_line.jpg [new file with mode: 0644]
website/images/dir.gif [new file with mode: 0644]
website/images/jabaws.png [new file with mode: 0644]
website/images/matrix_bg6.jpg [new file with mode: 0644]
website/images/minus.png [new file with mode: 0644]
website/images/mm_spacer.gif [new file with mode: 0644]
website/images/panel_bg.gif [new file with mode: 0644]
website/images/panel_bg.jpg [new file with mode: 0644]
website/images/panel_bg_long.gif [new file with mode: 0644]
website/images/plus.png [new file with mode: 0644]
website/images/uod.gif [new file with mode: 0644]
website/images/uod_h.gif [new file with mode: 0644]
website/images/uod_lt.gif [new file with mode: 0644]
website/images/vm_welcome_screen.png [new file with mode: 0644]
website/images/vmb_virtual.png [new file with mode: 0644]
website/images/ws-structure.png [new file with mode: 0644]
website/index.html [new file with mode: 0644]
website/man_about.html [new file with mode: 0644]
website/man_client.html [new file with mode: 0644]
website/man_configuration.html [new file with mode: 0644]
website/man_dev.html [new file with mode: 0644]
website/man_servervm.html [new file with mode: 0644]
website/man_serverwar.html [new file with mode: 0644]
website/manual_qs_client.html [new file with mode: 0644]
website/manual_qs_va.html [new file with mode: 0644]
website/manual_qs_war.html [new file with mode: 0644]
website/print.css [new file with mode: 0644]
website/prototype-1.6.0.3.js [new file with mode: 0644]
website/quick_start.html [new file with mode: 0644]
website/ws.css [new file with mode: 0644]

diff --git a/website/Example_template.pdf b/website/Example_template.pdf
new file mode 100644 (file)
index 0000000..20dc74f
Binary files /dev/null and b/website/Example_template.pdf differ
diff --git a/website/contacts.html b/website/contacts.html
new file mode 100644 (file)
index 0000000..21a4fc4
--- /dev/null
@@ -0,0 +1,74 @@
+<!DOCTYPE html PUBLIC "XHTML 1.0 Strict"\r
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<?xml version="1.0" encoding="UTF-8">\r
+<head>\r
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />\r
+<meta name="Last-modified" content="Mon, 4 Apr 2011 12:00:00 GMT"/>\r
+<title>Java Bioinformatics Analysis Web Services (JABAWS) download\r
+page</title>\r
+<link href="ws.css" rel="stylesheet" type="text/css" />\r
+<script type="text/javascript" src="prototype-1.6.0.3.js">\r
+        \r
+</script>\r
+</head>\r
+<body>\r
+<div id="page">\r
+<div id="banner">\r
+<table> \r
+<tr><td style="width:130px;"><a href="http://www.dundee.ac.uk"><img src="images/uod_lt.gif"  alt="University of Dundee" class="logo"  title="University of Dundee" longdesc="http://www.dundee.ac.uk"/></a></td>\r
+<td class="bg"><img src="images/jabaws.png" title="JABAWS:MSA" alt="JABAWS:MSA"/></td>\r
+<td class="bg"><img src="images/align.png"/></td>\r
+</tr>\r
+</table></div>\r
+\r
+<!-- banner end-->\r
+<div id="wrapper">\r
+<div id="panel"><a href="index.html">Home</a> \r
+<a href="quick_start.html">Getting Started</a> \r
+<a href="man_about.html">Manual</a> \r
+<a href="download.html">Download</a> \r
+<a class="selected" href="contacts.html">Contact Us</a>\r
+<a href="http://www.compbio.dundee.ac.uk">Barton Group</a> \r
+</div>\r
+\r
+<!-- panel end-->\r
+<div id="content">\r
+  \r
+<h2 id="headtitle">Contact Us</h2>\r
+<h3>Mailing List</h3>\r
+<p>Please feel free to post your questions/issues to the <a href="http://www.jalview.org/mailman/listinfo/jabaws-discuss">jabaws-discuss</a> mailing list. </p>\r
+<h3>Contact Details</h3>\r
+<p>The Barton Group <br/>\r
+   College of Life Sciences<br/>\r
+   University of Dundee<br/>\r
+   Dow Street<br/>\r
+   Dundee, <br/>\r
+   DD1 5EH, <br/>\r
+   Scotland, UK</p>\r
+<!--body end -->\r
+</div>\r
+\r
+<div id="copyright">Last update: 1 April 2011<br />\r
+ Peter Troshin and Geoff Barton, The Barton Group, University of\r
+Dundee, UK</div>\r
+\r
+\r
+</div> <!-- wrapper end-->\r
+\r
+<!-- Google analitics -->\r
+<script type="text/javascript">\r
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");\r
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));\r
+</script>\r
+<script type="text/javascript">\r
+try{\r
+var pageTracker = _gat._getTracker("UA-5356328-1");\r
+pageTracker._trackPageview();\r
+} catch(err) {}\r
+</script>\r
+\r
+</div> <!-- page end-->\r
+</body>\r
+</html>\r
+\r
diff --git a/website/develhome.html b/website/develhome.html
new file mode 100644 (file)
index 0000000..eeca0f2
--- /dev/null
@@ -0,0 +1,128 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />\r
+<title>Java Bioinformatics Analyses Web Services (JABAWS) developers documentation</title>\r
+<link href="ws.css" rel="stylesheet" type="text/css" media="screen,  projection, handheld, tv" />\r
+<link rel="stylesheet" type="text/css" media="print" href="print.css"/>\r
+\r
+<script type="text/javascript" src="prototype-1.6.0.3.js"></script>\r
+\r
+</head>\r
+<body>\r
+<div id="page">\r
+<div id="banner">\r
+<table> \r
+<tr><td style="width:130px;"><a href="http://www.dundee.ac.uk"><img src="images/uod_lt.gif"  alt="University of Dundee" class="logo"  title="University of Dundee" longdesc="http://www.dundee.ac.uk"/></a></td>\r
+<td class="bg"><img src="images/jabaws.png" title="JABAWS:MSA" alt="JABAWS:MSA"/></td>\r
+<td class="bg"><img src="images/align.png"/></td>\r
+</tr>\r
+</table>\r
+</div><!-- banner end-->\r
+\r
+<div id="wrapper">\r
+<div id="panel">\r
+       <a class="selected" href="index.html">Devel Home</a>\r
+       <a href="http://www.compbio.dundee.ac.uk/jabaws">JABAWS Production</a>\r
+<a href="http://www.compbio.dundee.ac.uk/user/www-jws2/wbstat" title="http://www.compbio.dundee.ac.uk/user/www-jws2/wbstat" rel="nofollow">Webalizer Access Stats</a>\r
+<a href="http://www.compbio.dundee.ac.uk/user/www-jws2/awstat_index.html" title="http://www.compbio.dundee.ac.uk/user/www-jws2" rel="nofollow">Awstat Access Stats</a></div>\r
+<!-- panel end-->\r
+<div id="content">\r
+\r
+  <h4>JABAWS Javadoc</h4>\r
+  <p><a href="dm_javadoc/index.html">Data model</a> javadoc- read this if your are coding against JABA Web Services</p>\r
+  <p><a href="full_javadoc/index.html">Complete</a> javadoc - for developers who want to use JABAWS framework and use Engines and Executables directly</p>\r
+  <h4>Starting up from the source code</h4>\r
+<p><a name="svn">SVN source repository:</a><a href="link to svn.lifesci.dundee.ac.uk/svn/barton/ptroshin/JABA_r1">https://svn.lifesci.dundee.ac.uk/svn/barton/ptroshin/JABA_r1</a><br/>\r
+The repository contains a complete JABAWS <a href="http://www.eclipse.org">Eclipse</a> project. To use Eclipse with this repository you need to install Eclipse SVN plugin which could be found here: http://subclipse.tigris.org/servlets/ProjectProcess?pageID=p4wYuA. Eclipse update web site address is <a href="http://subclipse.tigris.org/update_1.4.x">http://subclipse.tigris.org/update_1.4.x</a> Take care to install 1.4.x version of the plugin, as SVN repository will not work with more recent clients. it would help to install TestNG plugin as well which could be downloaded from <a href="http://testng.org/doc/download.html">http://testng.org/doc/download.html</a>. Please note however that no generated code is stored in the repository. That is to say that if you like to obtain client or server packages it is better to download them from the download section of this web site. Of cause If you want to make a modification to the source code you would need to generate distributives yourself. To do that first generate JAX-WS artifacts using <span class="hightlight">build-server</span> task from <span class="hightlight">wsbuild.xml</span> ant script, than you could use build.xml tasks to generate any of the distributives you need. </p>\r
+<h4>Structure of the project</h4>\r
+<img style="padding:0 1em;" align="left" src="images/ws-structure.png" alt="JABAWS layers" />\r
+<p>Layers in the source code are defined in a different source folders which are: \r
+<br/><span class="hightlight">/webservices<br />\r
+  /runner<br />\r
+  /engine<br />\r
+  /datamodel</span></p>\r
+<p style="clear:both">JABAWS project is split into 4 layers. From bottom-up the first layer consists from the value classes used by all other layers of the hierarchy, in particular web services. So, to be able to use JABAWS one needs to have these classes. At the same time classes on this layer does not have any dependencies on the layers above.</p>\r
+<p>The second layer contains code for execution of the wrappers, which are the abstraction describing native executables. The code on this level code engine. JABAWS can execute tasks locally that is on the same machine as JVM and on the cluster. Thus currently code on this layer contain two engines. This layer depends on the layer underneath, the data model layer, but is completely independent from the code above.</p>\r
+<p>The third layer consists of the wrappers for the native executables and classes to handle their configuration. It depends on the engines and the data model, but know nothing about the web services.</p>\r
+<p>Finally, the upper layer contains the web services, that depend on all the layers below.</p>\r
+<p>The layer isolation is archived though specially designed compilation task which is executed sequentially in several stages so that the first layer compiles before any other layers, second layer compiles after that and process continies before all the code is compiled.  Any violation of the layer boundaries results in the compilation failure. Use Ant &quot;Compile&quot; or &quot;Complile_with_debug&quot; tasks to perform the staged compilation.</p>\r
+<p>A client package contains only classes from data model layer and a simple web services client. Framework package is for anyone who want to use JABAWS framework for controlling native executables in local or cluster environments. Framework exclude the web services layer. Server package contains all the code.</p>\r
+\r
+<h4>Running tests</h4>\r
+<p>The test results for the JABAWS package offered for download can be found here: <a href="http://www.compbio.dundee.ac.uk/user/www-jws2/tests/index.html">Test Results</a><br/>\r
+JABAWS uses <a href="http://testng.org/doc/index.html">TestNG</a> for testing. There is a TestNG plugin available for Eclipse which has functionality similar to JUnit. However, no plugins are necessary to run the test cases, as testng jar is supplied with JABAWS together with an ant tasks to run the test cases. </p>\r
+<p>The best way to ensure that JABAWS framework is completely functional on your system is to run all test cases. \r
+Test cases tests all aspects of JABAWS functionality. Consequently, one need to have non windows operation system and support of the cluster to be able to run all tests. If your system does not support cluster, then you could run all test excluding those that depends on the cluster.\r
+Several testing groups are supported: \r
+<ul>\r
+<li>All tests (Test)</li>\r
+<li>Cluster tests (Run_cluster_dependent_test)</li>\r
+<li>Cluster independent tests () </li>\r
+<li>Windows only tests (All_cluster_independent_windows_only_tests) </li>\r
+<li>Performance and stability tests (Long_tests) </li>\r
+<li>Re-run failed tests (Rerun_failed_tests) </li>\r
+<li>Run custom test (CustomTest) </li>\r
+</ul>\r
+<p>To run the tests you need to download all sources from <a href="#svn">repository</a>. Once you have done that, enter into the command line mode, change directory to the project directory and type: \r
+  <span class="code">ant -f build.xml &lt;test group name&gt;</span>    </p>\r
+  <p>. Make sure you have <a href="http://ant.apache.org/">Apache Ant</a> \r
+    installed and path to ant executable is defined in your path environmental variable. \r
+    Replace test group name with the one of the names given in the list above to run required group of tests e.g for running cluster only tests \r
+    use the following \r
+    command: <span class="code">ant -f build.xml Run_cluster_dependent_test</span>\r
+    If you work under Linux you could use a simple script from the root folder of repository called <span class="hightlight">runtests.sh</span> This script simply contains a collection of the test commands described above and paths to java home directory and an ant executable, which you can define once for your system and then reuse.\r
+    </p>\r
+  </p>\r
+  <p>A handy feature of TestNG is its ability to re-run failed tests. Failed test ant file is stored in <span class="hightlight">test-output/testng-failed.xml</span>. and is used in the ant task called <span class="hightlight">Rerun_failed_tests</span>. So re-running failed tests requires no more work than running any other test group and could be accomplished with the command: <span class="code">ant -f build.xml Rerun_failed_tests</span> CustomTest runs the test defined in the project root directory file called <span class="hightlight">temp-testng-customsuite.xml</span>. This file is generated by TestNG plugin every time you run the test from Eclipse. Thus an easy way to run a test in a different environment is to run it from Eclipse first and then from ant using a custom test procedure. </p>\r
+  <p class="hightlight">For cluster execution make sure that the property LD_LIBRARY_PATH defined in build.xml points to cluster engine LD libraries directory in your local system.</p>\r
+\r
+ <h4>Preparing distributive's</h4>\r
+  <p>There are a number of ant tasks aimed for preparing distributives for download.\r
+  Currently a few types of JABAWS packages are offered \r
+  <ol>\r
+         <li>Client only (contains classes required to access JABA Web Services)</li>\r
+         <li>Platform specific JABAWS (windows and other)</li>\r
+         <li>JABA Web Services without JAXWS libraries ( a the runtime dependency) </li>\r
+         <li>JABAWS without binaries</li>\r
+         <li>JABAWS without binaries and jax-ws </li>\r
+         <li>JABAWS framework </li>\r
+  </ol>\r
+  </p>\r
+  Corresponding build task names are: \r
+  <ol>\r
+        <li>min-jaba-client</li>\r
+        <li>jaba-windows, jaba-complete</li>\r
+        <li>jaba-without-jaxws</li>\r
+     <li>jaba-no-binaries</li>\r
+     <li>jaba-no-jaxws-no-binaries</li>\r
+     <li>full-jaba-client</li>\r
+  </ol>\r
+\r
+  <p>The easiest way to build all distributives is to call <span class="hightlight">build-all </span>ant task. There are more tasks defined in build.xml than described here. They are mostly self explanatory.  </p>\r
+  <p class="hightlight">If you made any changes to the data model and would like to generate a complete JABAWS distro make sure you have rebuilt jaxws artifact as described below.  </p>\r
+  <h4>Building web services artifacts</h4>\r
+<p>Server side artifacts should be rebuild whenever the data model, meta model or MSA interface were changed. To do that run build-server task from wsbuild.xml ant build file. WSDL files will be generated in <span class="hightlight">webservices/compbio/ws/server/resource</span> directory. It is not necessary to edit them if any of the JABAWS clients are used. However, if you would like to generate portable artifacts using wsimport based on the generated WSDL files then, <span class="code">&lt;soap:address location=&quot;REPLACE_WITH_ACTUAL_URL&quot;/&gt;</span></p>\r
+\r
+<p>must be replaced with an actual server URL including the web services context path. For example: </p>\r
+<p class="code">http://www.compbio.ac.uk:8080/ws</p>\r
+<p>JABAWS are the standard JAX-WS web services, which are WS-I basic profile compatible. </p>\r
+</div>\r
+<!-- content end--> \r
+<div id="copyright">Last update: 19 August 2010<br/>Peter Troshin, The Barton Group, University of Dundee, UK</div>\r
+</div><!-- wrapper end-->\r
+</div> <!-- page end-->\r
+<!-- Google analitics -->\r
+<script type="text/javascript">\r
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");\r
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));\r
+</script>\r
+<script type="text/javascript">\r
+try{\r
+var pageTracker = _gat._getTracker("UA-5356328-1");\r
+pageTracker._trackPageview();\r
+} catch(err) {}\r
+</script>\r
+</body>\r
+</html>\r
+\r
diff --git a/website/download.html b/website/download.html
new file mode 100644 (file)
index 0000000..c64991e
--- /dev/null
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "XHTML 1.0 Strict"\r
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<meta http-equiv="Content-Type" content=\r
+"text/html; charset=iso-8859-1" />\r
+<meta name="Last-modified" content="Mon, 7 Apr 2011 18:00:00 GMT"/>\r
+<title>Java Bioinformatics Analysis Web Services (JABAWS) download\r
+page</title>\r
+<link href="ws.css" rel="stylesheet" type="text/css" />\r
+<script type="text/javascript" src="prototype-1.6.0.3.js">\r
+        \r
+</script>\r
+</head>\r
+<body>\r
+<div id="page">\r
+<div id="banner">\r
+<table> \r
+<tr><td style="width:130px;"><a href="http://www.dundee.ac.uk"><img src="images/uod_lt.gif"  alt="University of Dundee" class="logo"  title="University of Dundee" longdesc="http://www.dundee.ac.uk"/></a></td>\r
+<td class="bg"><img src="images/jabaws.png" title="JABAWS:MSA" alt="JABAWS:MSA"/></td>\r
+<td class="bg"><img src="images/align.png"/></td>\r
+</tr>\r
+</table></div>\r
+\r
+<!-- banner end-->\r
+<div id="wrapper">\r
+<div id="panel"><a href="index.html">Home</a> \r
+<a href="quick_start.html">Getting Started</a> \r
+<a href="man_about.html">Manual</a> \r
+<a class="selected" href="download.html">Download</a> \r
+<a href="contacts.html">Contact Us</a>\r
+<a href="http://www.compbio.dundee.ac.uk">Barton Group</a> \r
+</div>\r
+\r
+<!-- panel end-->\r
+<div id="content">\r
+  <h2 id="headtitle" style="text-align:left">JABAWS Server Virtual Machine</h2>\r
+  <p><span style="text-align:left">JABAWS virtual machine is a way of running fully functional JABA Web Services on your own computer. To use virtual machine (VM) you have to install a software for running it. We would recommend <a href="http://www.vmware.com/products/player">VMWare Player</a> for Windows and Linux users. There is also an  <a href="http://www.virtualbox.org/wiki/Download_Old_Builds_3_2">Oracle VirtualBox</a> (version 3.2.12) for Mac users. Both are free and installation is simple.  <a href="http://www.jalview.org/download.html">Jalview</a></span> can <a href="man_servervm.html#jalviewWithJaba">use your local JABAWS VM</a>. </p>\r
+  <ul>\r
+    <li> JABAWS Virtual Appliance: <a href="http://www.compbio.dundee.ac.uk/jabaws/archive/jabaws-vm.zip">download</a> (520M)</li>\r
+    </ul>\r
+  <p>Please check out our <a href="man_servervm.html#whenvm">manual</a> for the detailed instructions. </p>\r
+\r
+\r
+<h2><a name="jabawswar" id="jabawswar"></a>JABAWS Server Web Application </h2>\r
+<p> The JABAWS Server Web Application aRchive (WAR) version is for you if you want to deploy JABAWS for many users e.g. your laboratory or if you are an expert user and want to have more control on JABAWS. Typically, you will have a cluster or at least a powerful server machine which all users are willing to use. If you only have a single server then, you may use JABAWS Server Virtual Appliance instead. The server is provided as a self-contained <a href="http://en.wikipedia.org/wiki/WAR_(Sun_file_format)">Web Application\r
+aRchive (WAR) </a> containing all necessary binaries. WAR file can be deployed on any\r
+ web application server\r
+<!-- Note - mention servlet 2.4 compliance here? -->supporting at least version 2.4 of the Java servlet specification, i.e. <a href="http://tomcat.apache.org/download-60.cgi">Tomcat 6.0</a>. </p>\r
+\r
+<ul>\r
+<li>A Complete Server for all platforms: <a href=\r
+"http://www.compbio.dundee.ac.uk/jabaws/archive/jaba.war">download</a>\r
+(45M)</li>\r
+</ul>\r
+\r
+\r
+<p>Please bear in mind that if you deploy JABAWS WAR on Windows, only the Muscle and Clustal web services will work! If you want to run the other web services on Windows, then use the JABAWS Server VM package instead.  \r
+  <!-- content end-->\r
+</p>\r
+\r
+<h2> <a name="minclient" id="minclient"></a>JABAWS Command Line Client </h2>\r
+<p>The command line client is an executable Java program for scripting against JABA web services.  Its also useful as an example of how to access JABAWS services if you intend to use JABAWS in your own program, with functions demonstrating how to discover command line parameters and presets supported by a service, and how to run, monitor and retrieve the results of a job. <em>Note: The client is used in the <a href="http://www.jalview.org/source/jalview_2_6_1.tar.gz">Jalview 2.6.1 source code</a> to autogenerate a graphical user interface for JABA services.</em></p>\r
+<ul>\r
+  <li>Command line client\r
+    <ul>\r
+        <li>binaries: <a href=\r
+"http://www.compbio.dundee.ac.uk/jabaws/archive/min-jaba-client.jar">download</a> (80 K)</li>\r
+      <li>source: <a href=\r
+"http://www.compbio.dundee.ac.uk/jabaws/archive/jaba-client-source.jar">download</a> (70 K)</li>\r
+    </ul>\r
+  </li>\r
+</ul>\r
+<p>The command line client will display help documentation if it is run with no arguments, the same information is also given in <a href="man_client.html#usingcclient">the command line client's manual page</a>. </p>\r
+<h2>Version </h2>\r
+<p>Current JABAWS version is 1.1 release date 7 April 2011. Please consult the <a href="change.log">change log</a> file for the breakdown of the changes. </p>\r
+<div class="source">\r
+<div class="header collapsed" onclick=\r
+"$(this).toggleClassName('collapsed'); $(this).next('.body').toggleClassName('collapsed');"\r
+ title="Click to open/close">The Source Code</div>\r
+\r
+<div class="body collapsed">\r
+<h2>The Complete Source Code</h2>\r
+<p>If you want to add another web service or modify JABAWS in any way just download a complete JABAWS source code. We offer the code under <a href=\r
+"http://www.apache.org/licenses/LICENSE-2.0.txt">Apache licence</a>.  The code archive contains the complete <a href=\r
+"http://www.eclipse.org">Eclipse</a> JABAWS project, but Eclipse is not\r
+  necessary to build it. Please examine the Ant build file (build.xml)\r
+  to build and test JABAWS from sources.</p>\r
+<ul>\r
+  <li>A complete Eclipse project package: <a href=\r
+"http://www.compbio.dundee.ac.uk/jabaws/archive/jaba-project.zip">download</a> (82M)</li>\r
+  <li>JABAWS source  only package: <a href=\r
+"archive/jaba-source.jar">download</a> (250K)</li>\r
+  </ul>\r
+\r
+<!--body end -->\r
+</div>\r
+\r
+<!--source end -->\r
+</div>\r
+\r
+</div>\r
+<!-- wrapper end-->\r
+<div id="copyright">Last update: 7 April 2011<br />\r
+ Peter Troshin and Geoff Barton, The Barton Group, University of\r
+Dundee, UK</div>\r
+\r
+</div><!-- page end-->\r
+<!-- Google analitics -->\r
+<script type="text/javascript">\r
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");\r
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));\r
+</script>\r
+<script type="text/javascript">\r
+try{\r
+var pageTracker = _gat._getTracker("UA-5356328-1");\r
+pageTracker._trackPageview();\r
+} catch(err) {}\r
+</script>\r
+</div>\r
+</body>\r
+</html>\r
+\r
diff --git a/website/images/VMware_booted.png b/website/images/VMware_booted.png
new file mode 100644 (file)
index 0000000..4740198
Binary files /dev/null and b/website/images/VMware_booted.png differ
diff --git a/website/images/VMware_copy_q.png b/website/images/VMware_copy_q.png
new file mode 100644 (file)
index 0000000..3da8b81
Binary files /dev/null and b/website/images/VMware_copy_q.png differ
diff --git a/website/images/VMware_cpu.png b/website/images/VMware_cpu.png
new file mode 100644 (file)
index 0000000..e1a7901
Binary files /dev/null and b/website/images/VMware_cpu.png differ
diff --git a/website/images/align.png b/website/images/align.png
new file mode 100644 (file)
index 0000000..1bdf51b
Binary files /dev/null and b/website/images/align.png differ
diff --git a/website/images/banner_bg.gif b/website/images/banner_bg.gif
new file mode 100644 (file)
index 0000000..3848fc4
Binary files /dev/null and b/website/images/banner_bg.gif differ
diff --git a/website/images/banner_bg1.gif b/website/images/banner_bg1.gif
new file mode 100644 (file)
index 0000000..982c50b
Binary files /dev/null and b/website/images/banner_bg1.gif differ
diff --git a/website/images/brickhead2.jpg b/website/images/brickhead2.jpg
new file mode 100644 (file)
index 0000000..333a185
Binary files /dev/null and b/website/images/brickhead2.jpg differ
diff --git a/website/images/brickhead2_line.jpg b/website/images/brickhead2_line.jpg
new file mode 100644 (file)
index 0000000..e35d216
Binary files /dev/null and b/website/images/brickhead2_line.jpg differ
diff --git a/website/images/dir.gif b/website/images/dir.gif
new file mode 100644 (file)
index 0000000..ceafb2f
Binary files /dev/null and b/website/images/dir.gif differ
diff --git a/website/images/jabaws.png b/website/images/jabaws.png
new file mode 100644 (file)
index 0000000..c9b340f
Binary files /dev/null and b/website/images/jabaws.png differ
diff --git a/website/images/matrix_bg6.jpg b/website/images/matrix_bg6.jpg
new file mode 100644 (file)
index 0000000..95da0e1
Binary files /dev/null and b/website/images/matrix_bg6.jpg differ
diff --git a/website/images/minus.png b/website/images/minus.png
new file mode 100644 (file)
index 0000000..ae4f575
Binary files /dev/null and b/website/images/minus.png differ
diff --git a/website/images/mm_spacer.gif b/website/images/mm_spacer.gif
new file mode 100644 (file)
index 0000000..35d42e8
Binary files /dev/null and b/website/images/mm_spacer.gif differ
diff --git a/website/images/panel_bg.gif b/website/images/panel_bg.gif
new file mode 100644 (file)
index 0000000..1b3030d
Binary files /dev/null and b/website/images/panel_bg.gif differ
diff --git a/website/images/panel_bg.jpg b/website/images/panel_bg.jpg
new file mode 100644 (file)
index 0000000..521b3d4
Binary files /dev/null and b/website/images/panel_bg.jpg differ
diff --git a/website/images/panel_bg_long.gif b/website/images/panel_bg_long.gif
new file mode 100644 (file)
index 0000000..1ceb786
Binary files /dev/null and b/website/images/panel_bg_long.gif differ
diff --git a/website/images/plus.png b/website/images/plus.png
new file mode 100644 (file)
index 0000000..865e538
Binary files /dev/null and b/website/images/plus.png differ
diff --git a/website/images/uod.gif b/website/images/uod.gif
new file mode 100644 (file)
index 0000000..4d58773
Binary files /dev/null and b/website/images/uod.gif differ
diff --git a/website/images/uod_h.gif b/website/images/uod_h.gif
new file mode 100644 (file)
index 0000000..ee3705e
Binary files /dev/null and b/website/images/uod_h.gif differ
diff --git a/website/images/uod_lt.gif b/website/images/uod_lt.gif
new file mode 100644 (file)
index 0000000..fe12457
Binary files /dev/null and b/website/images/uod_lt.gif differ
diff --git a/website/images/vm_welcome_screen.png b/website/images/vm_welcome_screen.png
new file mode 100644 (file)
index 0000000..274f109
Binary files /dev/null and b/website/images/vm_welcome_screen.png differ
diff --git a/website/images/vmb_virtual.png b/website/images/vmb_virtual.png
new file mode 100644 (file)
index 0000000..f64725f
Binary files /dev/null and b/website/images/vmb_virtual.png differ
diff --git a/website/images/ws-structure.png b/website/images/ws-structure.png
new file mode 100644 (file)
index 0000000..791ad9a
Binary files /dev/null and b/website/images/ws-structure.png differ
diff --git a/website/index.html b/website/index.html
new file mode 100644 (file)
index 0000000..8c73f54
--- /dev/null
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<meta name="Last-modified" content="Mon, 4 Apr 2011 12:00:00 GMT"/>\r
+<title>Java Bioinformatics Analyses Web Services (JABAWS) main\r
+page</title>\r
+<link href="ws.css" rel="stylesheet" type="text/css" media=\r
+"screen, projection, handheld, tv" />\r
+<link rel="stylesheet" type="text/css" media="print" href=\r
+"print.css" />\r
+<script type="text/javascript" src="prototype-1.6.0.3.js">\r
+        \r
+</script></head>\r
+<body>\r
+<div id="page">\r
+<div id="banner">\r
+<table> \r
+<tr><td style="width:130px;"><a href="http://www.dundee.ac.uk"><img src="images/uod_lt.gif"  alt="University of Dundee" class="logo"  title="University of Dundee" longdesc="http://www.dundee.ac.uk"/></a></td>\r
+<td class="bg"><img src="images/jabaws.png" title="JABAWS:MSA" alt="JABAWS:MSA"/></td>\r
+<td class="bg"><img src="images/align.png" alt="Multiple sequence alignment"/></td>\r
+</tr>\r
+</table>\r
+</div>\r
+\r
+<!-- banner end-->\r
+<div id="wrapper">\r
+<div id="panel">\r
+ <a class="selected" href="index.html">Home</a> \r
+ <a href="quick_start.html">Getting Started</a> \r
+ <a href="man_about.html">Manual</a> \r
+ <a href="download.html">Download</a> \r
+ <a href="contacts.html">Contact Us</a>\r
+ <a href="http://www.compbio.dundee.ac.uk" title="University of Dundee, The Barton Group" >Barton Group</a></div>\r
+\r
+<!-- panel end-->\r
+<div id="content">\r
+<h2 id="headtitle">JABAWS</h2>\r
+<p style="color:black; font-weight:normal; text-align:left;"><span style="border-bottom:dotted 1px #666" title="JAva Bioinformatics Analysis Web Services for Multiple Sequence Alignment">JABAWS:MSA</span> provides five web services for multiple sequence alignment: <a href="http://www.clustal.org/">Clustal W</a>, <a href=\r
+"http://align.bmr.kyushu-u.ac.jp/mafft/software/">MAFFT</a>, <a href="http://www.drive5.com/muscle">MUSCLE</a>, <a href=\r
+"http://www.tcoffee.org/Projects_home_page/t_coffee_home_page.html"> TCOFFEE</a> and <a href="http://probcons.stanford.edu/">PROBCONS</a> conveniently packaged to run on your local computer, server or cluster. \r
+<span style="color:black; font-weight:normal; text-align:left;">JABA Web Services can be accessed from the <a href="http://www.jalview.org">Jalview</a> multiple sequence alignment editor and analysis workbench  to allow multiple        alignment calculations limited only by your own local computing        resources.</span></p>\r
+\r
+<div id="mainpagefeatures">\r
+<table>\r
+<tr><td>\r
+  <div class="brick">  \r
+  <div class="brick_header"><h2>For Users</h2></div>\r
+    <div class="brick_content">\r
+        <strong>The Server: </strong><a href="http://www.compbio.dundee.ac.uk/jabaws/archive/jabaws-vm.zip">JABAWS Virtual Appliance:</a> (520M)\r
+       <br/>\r
+       <strong>The Client: </strong><a href="http://www.jalview.org/download.html">Jalview</a> (18M)\r
+               <p>To use JABA Web Services on most operating systems, just download and <a href="manual_qs_va.html#qsc">install</a> the JABAWS Virtual Appliance (VA) and point Jalview at it.</p>\r
+     </div>\r
+  </div>\r
+  </td>\r
+  </tr>\r
+  <tr>\r
+    <td><div class="brick">\r
+            <div class="brick_header"><h2>For System Administrators</h2></div>\r
+                <div class="brick_content">\r
+                  <p><strong>The Server: </strong><a href=\r
+"http://www.compbio.dundee.ac.uk/jabaws/archive/jaba.war">JABAWS Web Application aRchive</a> (45M)                </p>\r
+                  <p>JABAWS requires a Servlet 2.4 compatible servlet container like Apache-Tomcat to run. Please check the quick start guide for <a href="manual_qs_war.html#qsc">installation instructions</a>.</p>\r
+                </div>\r
+               </div></td>\r
+  </tr>\r
+  <tr>\r
+    <td><div class="brick">\r
+            <div class="brick_header"><h2>For Bioinformaticians/Developers</h2></div>\r
+                <div class="brick_content">\r
+<strong>The Server: </strong><a href=\r
+"http://www.compbio.dundee.ac.uk/jabaws/archive/jaba.war">JABAWS Web Application aRchive</a>  (45M)\r
+  <br/>\r
+  <strong>The Client: </strong>\r
+      Command Line Client <a href="http://www.compbio.dundee.ac.uk/jabaws/archive/min-jaba-client.jar">binary</a> | <a href=\r
+"http://www.compbio.dundee.ac.uk/jabaws/archive/jaba-client-source.jar">source</a> \r
+         <!-- <li><a href="http://www.jalview.org/download.html">Jalview</a> (18M)</li> -->\r
+  \r
+  \r
+<p>You can either use the JABAWS Virtual Appliance or the JABAWS Web Application aRchive (WAR) from your own computer or a lab server. The WAR version gives greater flexibility but requires a bit more configuration. Alternatively you can just script against our public server (see below) with the command line client or you own script. \r
+Check out the <a href="manual_qs_client.html#qsc">quick start guide</a> for further details.</p>\r
+\r
+                </div>\r
+               </div></td>\r
+  </tr>\r
+</table>\r
+</div>\r
+\r
+<h3 style="margin:0;">Public JABAWS Server</h3>\r
+<p> You can access our public JABA Web Services with our <a href="download.html">command line client</a>, <a href="http://www.jalview.org/download.html">Jalview</a>, or with your own program. Jalview is configured to use this public JABAWS server by default.<br/></p>\r
+<ul>\r
+  <li>The JABAWS public web services address is <strong>http://www.compbio.dundee.ac.uk/jabaws</strong> </li>\r
+  <li>A detailed web services description is available from here: <a href="http://www.compbio.dundee.ac.uk/jabaws/ClustalWS?"\r
+title="http://www.compbio.dundee.ac.uk/jabaws/ClustalWS?" rel=\r
+"nofollow">WSDL List</a></li>\r
+</ul>\r
+<p>The maximum number of sequences you can align with this public web service is 1000 with up to 1000 letters average length. Should you find this to be insufficient for your needs, or if you are concerned about privacy or on an unreliable network connection, then you can <a href="quick_start.html">download</a> and run the JABAWS Server on your own hardware.</p>\r
+\r
+\r
+<h3>Publication</h3>\r
+<p>Peter V. Troshin, James B. Procter and Geoffrey J. Barton &quot;JABAWS:MSA Distributed Web Services for Bioinformatics: Multiple Sequence Alignment&quot;\r
+- paper submitted.</p>\r
+</div>\r
+\r
+<!-- content end-->\r
+<div id="copyright">Last update: 1 April 2011<br />\r
+ This site is best viewed in Firefox 3.6, Google Chrome 10 or Internet Explorer 8 </div>\r
+</div>\r
+\r
+<!-- wrapper end-->\r
+</div>\r
+<!-- Google analitics -->\r
+<script type="text/javascript">\r
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");\r
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));\r
+</script>\r
+<script type="text/javascript">\r
+try{\r
+var pageTracker = _gat._getTracker("UA-5356328-1");\r
+pageTracker._trackPageview();\r
+} catch(err) {}\r
+</script>\r
+<!-- page end-->\r
+</body>\r
+</html>\r
+\r
diff --git a/website/man_about.html b/website/man_about.html
new file mode 100644 (file)
index 0000000..ac1c686
--- /dev/null
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "XHTML 1.0 Strict" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<meta name="Last-modified" content="Mon, 4 Apr 2011 12:00:00 GMT"/>\r
+<title>Java Bioinformatics Analyses Web Services (JABAWS) manual - About</title>\r
+<link href="ws.css" rel="stylesheet" type="text/css" media="screen,  projection, handheld, tv" />\r
+<link rel="stylesheet" type="text/css" media="print" href="print.css"/>\r
+\r
+<script type="text/javascript" src="prototype-1.6.0.3.js"></script>\r
+</head>\r
+<body>\r
+<div id="page">\r
+<div id="banner">\r
+<table> \r
+<tr><td style="width:130px;"><a href="http://www.dundee.ac.uk"><img src="images/uod_lt.gif"  alt="University of Dundee" class="logo"  title="University of Dundee" longdesc="http://www.dundee.ac.uk"/></a></td>\r
+<td class="bg"><img src="images/jabaws.png" title="JABAWS:MSA" alt="JABAWS:MSA"/></td>\r
+<td class="bg"><img src="images/align.png"/></td>\r
+</tr>\r
+</table>\r
+</div><!-- banner end-->\r
+<div id="wrapper">\r
+<div id="panel">\r
+       <a href="index.html">Home</a>\r
+    <a href="quick_start.html">Getting Started</a> \r
+        <a class="selected" href="man_about.html">Manual</a> \r
+       <div id="submenu">\r
+               <a class="selected" href="man_about.html">About</a>\r
+               <a href="man_servervm.html" title="JABAWS Server as Virtual Appliance">Server VA</a>\r
+               <a href="man_serverwar.html" title="JABAWS Server as Web Application aRchive">Server WAR</a>\r
+               <a href="man_configuration.html" >Server<br/>\r
+               Configuration</a>\r
+               <a href="man_client.html" title="JABAWS Command Line Client">CMD Client</a>\r
+               <a href="man_dev.html" title="Accessing JABAWS from your program">Accessing<br/>\r
+               JABAWS</a>      \r
+       </div>\r
+       <a href="download.html">Download</a>\r
+       <a href="contacts.html">Contact Us</a>\r
+       <a href="http://www.compbio.dundee.ac.uk">Barton Group</a></div>\r
+<!-- panel end-->\r
+<div id="content">\r
+\r
+<h2 id="headtitle">JABAWS MANUAL</h2>\r
+<h2>About</h2>\r
+\r
+<ul>\r
+  <li><a href="#wisjaba">What is JABAWS?</a></li>\r
+  <li><a href="#wjaba">JABAWS Benefits</a></li>\r
+  <li><a href="#alprog">JABA Web Services Programs </a></li>\r
+  <li><a href="#jabaclient">What is JABAWS Client</a>?</li>\r
+  <li><a href="#cmdclient">Programmatic access to JABAWS</a></li>\r
+  </ul>\r
+\r
+\r
+<h3><a name="wisjaba" id="wisjaba"></a>What is JABAWS?</h3>\r
+<p>JABAWS stands for JAva Bioinformatics Analysis Web Services. As the name suggests, JABAWS is a collection of web services for bioinformatics, and currently provides services that make it easy to access well-known multiple sequence alignment programs (see <a href="#alprog">the list of currently supported programs</a>) from <a href="http://www.jalview.org">Jalview</a>.\r
+ However, the scope of JABAWS is not limited to multiple sequence alignment programs. Future versions of JABAWS will incorporate protein disorder prediction, BLAST, PSIBLAST and HMMER database searches and many other tools.</p>\r
+<h4>Getting JABAWS</h4>\r
+<p>JABAWS consists of a server and client, but unlike most bioinformatics web service systems, you can download and run both parts on your own computer! If you want a server just for yourself, then download and install the JABAWS Virtual Appliance. It requires no configuration and is simple to install. If you want to install JABAWS for your lab or institution then download the JABAWS Web Application aRchive. It is slightly more complicated to configure but is very straightforward too. Finally, if you want to script against any version of JABAWS or are interested in writing your own client, the JABAWS command line client is what you need. </p>\r
+<h3><a name="wjaba" id="wjaba"></a>JABAWS Benefits</h3>\r
+<ul>\r
+<li>Can be deployed on most operating systems, as a VMWare or OpenBox compatible Virtual Appliance or a Tomcat Java Web Application.</li>\r
+<li>Comes complete with sources and binaries for all the bioinformatics programs that it runs.</li>\r
+<li>Can operate as a stand alone server or one that submits jobs to a cluster <em>via</em> <a href="http://www.drmaa.org/">DRMAA</a>.</li>\r
+<li>Easy to access from <a href="http://www.jalview.org">Jalview</a> using its graphical client, or using the JABAWS command line client.</li>\r
+<li>Clients can submit jobs to any JABAWS servers that you might want to access, such as the one running on your local computer, your lab's server, or the publicly available services at the <a href="http://www.compbio.dundee.ac.uk/">University of Dundee</a>.</li>\r
+<li>Local or intranet installation eliminates any security concerns you might have about sending sensitive data over the internet.</li>\r
+<li>Wide range of configuration options to control size of jobs accepted by a server and the command line options available for the program run by a service.</li>\r
+</ul>\r
+<h3><a name="alprog" id="alprog"/>JABA Web Services Programs </h3>\r
+<p> JABAWS currently provides access to the following programs:</p>\r
+<ul>\r
+  <li><a href="http://www.clustal.org/">ClustalW</a> (version 2.0.12)</li>\r
+  <li><a href="http://align.bmr.kyushu-u.ac.jp/mafft/software/">Mafft</a> (version 6.713)</li>\r
+  <li><a href="http://www.drive5.com/muscle">Muscle</a> (version 3.7) </li>\r
+  <li><a href="http://www.tcoffee.org/Projects_home_page/t_coffee_home_page.html">Tcoffee</a> (version 8.14) </li>\r
+  <li><a href="http://probcons.stanford.edu/">Probcons</a> (version 1.12)</li>\r
+  </ul>\r
+\r
+<h3><a name="jabaclient" id="jabaclient"></a>What is JABAWS client?</h3>\r
+<p>A JABAWS client is a program that lets you run the bioinformatics methods for which a JABAWS server provides web services. \r
+The most basic JABAWS client is a command line Java application which can call any of the JABAWS web services methods \r
+on any instance of JABAWS Server that it can reach over the web. It is useful if you \r
+want to test, or execute the programs provided by a JABAWS server in your own scripts, and do not want to handle any web service \r
+specific details. The client is open source, so you can also use its source code to find \r
+out how to work with JABA Web Services if you would like to write your own client \r
+software. <a href="http://www.jalview.org/">Jalview</a>, which is a multiple sequence alignment and analysis application, provides a graphical JABAWS client. This client has the same \r
+functionality as the command line client, but instead allows JABAWS services to be accessed in a more user-friendly manner, through a graphical user interface.</p>\r
+<h3><a name="cmdclient" id="cmdclient"></a>Programmatic access to JABAWS </h3>\r
+<p>JABA Web Services are WS-I basic profile compliant, which means they can be accessed using \r
+any programming language or system that can utilize standard SOAP web services. \r
+The WSDL for each service is published on the JABAWS home page, and you can use this to automatically generate \r
+service bindings for your program. If you use Java, however, then you may wish to use our \r
+<a href="download.html#minclient">client package</a> to access JABAWS. \r
+This package is based on the autogenerated source code produced by <span class="hightlight">wsimport</span>, which is the Java tool for creating web service bindings; \r
+but in addition, offers some additional methods which simplify working with JABAWS. For more information please refer to the \r
+<a href="dm_javadoc/index.html">data model javadoc</a>.\r
+</p>\r
+</div> \r
+<!-- about end-->\r
+<!-- content end--> \r
+<div id="copyright">Last update: 1 April 2011<br/>\r
+Peter Troshin, Jim Procter and Geoff Barton, The Barton Group, University of Dundee, UK</div>\r
+\r
+</div>\r
+</div><!-- wrapper end-->\r
+\r
+<!-- Google analitics -->\r
+<script type="text/javascript">\r
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");\r
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));\r
+</script>\r
+<script type="text/javascript">\r
+try{\r
+var pageTracker = _gat._getTracker("UA-5356328-1");\r
+pageTracker._trackPageview();\r
+} catch(err) {}\r
+</script>\r
+\r
+</body>\r
+</html>\r
+\r
diff --git a/website/man_client.html b/website/man_client.html
new file mode 100644 (file)
index 0000000..ce35521
--- /dev/null
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "XHTML 1.0 Strict"\r
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<meta name="Last-modified" content="Mon, 4 Apr 2011 12:00:00 GMT"/>\r
+<title>Java Bioinformatics Analyses Web Services (JABAWS) Command Line Client manual</title>\r
+<link href="ws.css" rel="stylesheet" type="text/css" media=\r
+"screen, projection, handheld, tv" />\r
+<link rel="stylesheet" type="text/css" media="print" href=\r
+"print.css" />\r
+<script type="text/javascript" src="prototype-1.6.0.3.js"></script>\r
+</head>\r
+<body>\r
+<div id="page">\r
+<div id="banner">\r
+<table> \r
+<tr><td style="width:130px;"><a href="http://www.dundee.ac.uk"><img src="images/uod_lt.gif"  alt="University of Dundee" class="logo"  title="University of Dundee" longdesc="http://www.dundee.ac.uk"/></a></td>\r
+<td class="bg"><img src="images/jabaws.png" title="JABAWS:MSA" alt="JABAWS:MSA"/></td>\r
+<td class="bg"><img src="images/align.png"/></td>\r
+</tr>\r
+</table></div><!-- banner end-->\r
+\r
+<div id="wrapper">\r
+<div id="panel"><a href="index.html">Home</a> \r
+  <a href="quick_start.html">Getting Started</a> \r
+  <a class="selected" href="man_about.html">Manual</a> \r
+       <div id="submenu">\r
+               <a href="man_about.html">About</a>\r
+               <a href="man_servervm.html" title="JABAWS Server as Virtual Appliance">Server VA</a>\r
+               <a href="man_serverwar.html" title="JABAWS Server as Web Application aRchive">Server WAR</a>\r
+               <a href="man_configuration.html" >Server<br/>\r
+               Configuration</a>\r
+               <a class="selected" href="man_client.html" title="JABAWS Command Line Client">CMD Client</a>\r
+               <a href="man_dev.html" title="Accessing JABAWS from your program">Accessing<br/>\r
+               JABAWS</a>      \r
+       </div>\r
+<a href="download.html">Download</a> \r
+<a href="contacts.html">Contact Us</a>\r
+<a href="http://www.compbio.dundee.ac.uk">Barton Group</a> \r
+</div>\r
+\r
+<!-- panel end-->\r
+<div id="content">\r
+<h2 id="headtitle">JABAWS MANUAL</h2>\r
+\r
+<h2><a name="usingcclient" id="usingcclient"></a>JABAWS Command Line Client Usage </h2>\r
+<p>The command line client comes as a part of <a href="download.html"> client package</a> which you are welcome to download. The command line client can be used to align sequences using any of JABAWS supported web services. The client is OS independent and supports most of the functions which can be accessed programmatically via <a href="dm_javadoc/index.html">JABAWS API</a>. Using this client you could align sequences using presets or custom parameters, please see examples of this below. Here is the list of options supported by the command line client. </p>\r
+<span class="code"><strong>Usage:</strong> java -jar &lt;path_to_jar_file&gt; -h=host_and_context -s=serviceName ACTION [OPTIONS]<br />\r
+-h=&lt;host_and_context&gt; - a full URL to the JABAWS web server including context path e.g. http://10.31.10.159:8080/ws<br />\r
+-s=&lt;ServiceName&gt; - one of [MafftWS, MuscleWS, ClustalWS, TcoffeeWS, ProbconsWS]\r
+</p>\r
+<br />\r
+<strong>ACTIONS:</strong><br />\r
+-i=&lt;inputFile&gt; - full path to fasta formatted sequence file, from which to align sequences<br />\r
+-parameters - lists parameters supported by web service<br />\r
+-presets - lists presets supported by web service<br />\r
+-limits - lists web services limits<br />\r
+Please note that if input file is specified other actions are ignored\r
+</p>\r
+<br />\r
+<strong> OPTIONS:</strong> (only for use with -i action):<br />\r
+-r=&lt;presetName&gt; - name of the preset to use<br />\r
+-o=&lt;outputFile&gt; - full path to the file where to write an alignment<br />\r
+-f=&lt;parameterInputFile&gt; - the name of the file with the list of parameters to use.<br />\r
+Please note that -r and -f options cannot be used together. Alignment is done with either preset or a parameters from the file, but not both!</span>\r
+<p>Align sequences from input.fasta file using Mafft web service with default settings, print alignment in Clustal format to console. </p>\r
+<p class="code">java -jar jabaws-min-client.jar -h=http://myhost.compbio.ac.uk:8080/jabaws -s=MafftWS -i=d:\input.fasta</p>\r
+<p>Content of input.fasta file is show below (please note sequences has been trimmed for clarity)<span class="code">&gt;Foobar<br />\r
+  MTADGPRELLQLRAAVRHRPQDFVAWL <br />\r
+  &gt;Bar<br />\r
+  MGDTTAGEMAVQRGLALHQ<br />\r
+  QRHAEAAVLLQQASDAAPE<br />\r
+  &gt;Foofriend<br />\r
+  MTADGPRELLQLRAAV</span></p>\r
+<p>Align as in above example, but write output alignment in a file out.clustal, using parameters defined in prm.in file</p>\r
+<p><span class="code">java -jar jabaws-min-client.jar -h=http://myhost.compbio.ac.uk:8080/jabaws  -s=MafftWS -i=d:\input.fasta -o=d:\out.clustal -f=prm.in </span></p>\r
+<p>The content of the prm.in file is shown below <span class="code">--nofft<br />\r
+  --noscore<br />\r
+  --fastaparttree<br />\r
+  --retree=10<br />\r
+  --op=2.2</span></p>\r
+<p>The format of the file is the same for all JABAWS web services. Parameters are specified in exactly the same way as for native executables - alignment programs like Mafft etc. So parameters which you can use with command line version of an alignment program can be used with JABAWS. Most of the settings controlling alignment process are supported, but the setting controlling output are not. This is due to the fact the output have to be handled by JABAWS, so must remain within its control. For a list of parameters supported by a web service see the next example. In <span class="hightlight">prm.in</span> parameters are separated by the new line, and name of the parameter is separated from its value with an equal sign. This format is constant no matter which JABAWS web service is used. <br />\r
+    <span class="code"> java -jar jabaws-min-client.jar -h=http://myhost.compbio.ac.uk:8080/jabaws -s=MafftWS -parameters</span></p>\r
+<p>The same client can be used to access JABAWS on different hosts. Just point the client to the host you want to use by changing the value of -h key. For example you used <span class="hightlight">-h=http://myhost.compbio.ac.uk:8080/jabaws</span> server, now you want to use another server to <span class="hightlight">-h=http://mylabserver.myuni.edu.</span> This comes handy if your favorite server is off and you need to do the job yesterday. </p>\r
+</div>\r
+\r
+<!-- content end-->\r
+<div id="copyright">Last update: 1 April 2011<br />\r
+ Peter Troshin, Jim Procter and Geoff Barton, The Barton Group, University of\r
+Dundee, UK</div>\r
+</div>\r
+\r
+<!-- wrapper end-->\r
+</div>\r
+<!-- page end-->\r
+\r
+<!-- Google analitics -->\r
+<script type="text/javascript">\r
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");\r
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));\r
+</script>\r
+<script type="text/javascript">\r
+try{\r
+var pageTracker = _gat._getTracker("UA-5356328-1");\r
+pageTracker._trackPageview();\r
+} catch(err) {}\r
+</script>\r
+</body>\r
+</html>\r
+\r
diff --git a/website/man_configuration.html b/website/man_configuration.html
new file mode 100644 (file)
index 0000000..5122e08
--- /dev/null
@@ -0,0 +1,437 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "XHTML 1.0 Strict"\r
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<meta name="Last-modified" content="Mon, 4 Apr 2011 12:00:00 GMT"/>\r
+<title>Java Bioinformatics Analyses Web Services (JABAWS) Server Configuration manual</title>\r
+<link href="ws.css" rel="stylesheet" type="text/css" media=\r
+"screen, projection, handheld, tv" />\r
+<link rel="stylesheet" type="text/css" media="print" href=\r
+"print.css" />\r
+<script type="text/javascript" src="prototype-1.6.0.3.js"></script>\r
+</head>\r
+<body>\r
+<div id="page">\r
+<div id="banner">\r
+<table> \r
+<tr><td style="width:130px;"><a href="http://www.dundee.ac.uk"><img src="images/uod_lt.gif"  alt="University of Dundee" class="logo"  title="University of Dundee" longdesc="http://www.dundee.ac.uk"/></a></td>\r
+<td class="bg"><img src="images/jabaws.png" title="JABAWS:MSA" alt="JABAWS:MSA"/></td>\r
+<td class="bg"><img src="images/align.png"/></td>\r
+</tr>\r
+</table></div><!-- banner end-->\r
+\r
+<div id="wrapper">\r
+<div id="panel"><a href="index.html">Home</a> \r
+  <a href="quick_start.html">Getting Started</a> \r
+  <a class="selected" href="man_about.html">Manual</a> \r
+       <div id="submenu">\r
+               <a href="man_about.html">About</a>\r
+               <a href="man_servervm.html" title="JABAWS Server as Virtual Appliance">Server VA</a>\r
+               <a href="man_serverwar.html" title="JABAWS Server as Web Application aRchive">Server WAR</a>\r
+               <a class="selected" href="man_configuration.html" >Server<br/>\r
+               Configuration</a>\r
+               <a href="man_client.html" title="JABAWS Command Line Client">CMD Client</a>\r
+               <a href="man_dev.html" title="Accessing JABAWS from your program">Accessing<br/>\r
+               JABAWS</a>      \r
+       </div>\r
+<a href="download.html">Download</a> \r
+<a href="contacts.html">Contact Us</a>\r
+<a href="http://www.compbio.dundee.ac.uk">Barton Group</a> \r
+</div>\r
+\r
+<!-- panel end-->\r
+<div id="content">\r
+<h2 id="headtitle">JABAWS MANUAL</h2>\r
+\r
+<h2>JABAWS Configuration </h2>\r
+<ul>\r
+  <li><a href="#defjabaconf">JABAWS Configuration </a></li>\r
+  <li><a href="#locEngConf">Local Engine Configuration</a></li>\r
+  <li><a href="#clustEngConf">Cluster Engine Configuration</a></li>\r
+  <li><a href="#exec">Executable Configuration</a></li>\r
+  <li><a href="#setexecenv">Defining Environment Variables for\r
+    Executables</a></li>\r
+  <li><a href="#mafftconf">Configure JABAWS to Work\r
+with Mafft</a></li>\r
+  <li><a href="#settinglimit">Limiting the size of the job accepted by JABAWS Server </a></li>\r
+  <li><a href="#diffbin">Using a different version of the alignment program with JABAWS</a></li>\r
+  <li><a href="#mixuse">Load balancing </a></li>\r
+  <li><a href="#confaccessright">Reviewing JABAWS configuration via web browser</a></li>\r
+  <li><a href="#testingJaba">Testing JABA Web Services</a></li>\r
+  <li><a href="#logs">JABAWS requests logging </a></li>\r
+  <li><a href="#logfiles">JABAWS internal logging </a></li>\r
+  <li><a href="#execstat">Monitoring JABAWS</a></li>\r
+  <li><a href="#warfile">JABAWS War File Content</a></li>\r
+  </ul>\r
+<h3><a name="defjabaconf" id="defjabaconf"></a>JABAWS Configuration </h3>\r
+<p>There are three parts of the system you can configure. The local\r
+and the cluster engines, and the paths to the individual executables for\r
+each engine. These settings are stored in configuration files\r
+within the web application directory (for an overview, then take a\r
+look at the <a href="#warfile">war file content table</a>). </p>\r
+<p>Initially, JABAWS is configured with only the local engine\r
+  enabled, with job output written to directory called &quot;jobsout&quot;\r
+  within the web application itself. This means that JABAWS will work\r
+  out of the box, but may not be suitable for serving a whole lab or\r
+  a university.</p>\r
+<h3><a name="locEngConf" id="locEngConf"></a>Local Engine Configuration</h3>\r
+\r
+<p>The Local execution engine configuration is defined in the\r
+properties file <span class="hightlight">conf/Engine.local.properties. </span>The supported\r
+configuration settings are:<br />\r
+ <span class="hightlight">engine.local.enable=true</span> - #\r
+enable or disable local engine, valid values true | false<br />\r
+ <span class=\r
+"hightlight">local.tmp.directory=D:\\clusterengine\\testoutput</span>\r
+- a directory to use for temporary files storage, optional,\r
+defaults to java temporary directory<br />\r
+ <span class="hightlight">engine.local.thread.number=4</span> -\r
+Number of threads for tasks execution (valid values between 1 and\r
+2x cpu. Where x is a number of cores available in the system).\r
+Optional defaults to the number of cores for core number &lt;=4 and\r
+number of cores-1 for greater core numbers.</p>\r
+\r
+<p>If the local engine going to be heavily loaded (which is often the case if you do not have a cluster) it is a good idea to increase\r
+the amount of memory available for the web application server. If\r
+you are using Apache-Tomcat, then you can define its memory\r
+settings in the JAVA_OPTS environment variable. To specify which\r
+JVM to use for Apache-Tomcat, put the full path to the JRE\r
+installation in the JAVA_HOME environment variable (We would\r
+recommend using Sun Java Virtual Machine (JVM) in preference to\r
+Open JDK). Below is an example of code which can be added to <span\r
+class="hightlight">&lt;tomcat_dir&gt;/bin/setenv.sh</span> script\r
+to define which JVM to use and a memory settings for Tomcat server.\r
+Tomcat server startup script (<span class=\r
+"hightlight">catalina.sh</span>) will execute <span class=\r
+"hightlight">setenv.sh</span> on each server start\r
+automatically.<br />\r
+ <span class="code">export\r
+JAVA_HOME=/homes/ws-dev2/jdk1.6.0_17/<br />\r
+ export JAVA_OPTS=&quot;-server -Xincgc -Xms512m -Xmx1024m&quot;</span></p>\r
+\r
+<h3><a name="clustEngConf" id="clustEngConf"></a>Cluster Engine Configuration</h3>\r
+\r
+<p>Supported configuration settings:<br />\r
+ <span class="hightlight">engine.cluster.enable=true</span> - #\r
+enable or disable local engine true | false, defaults to\r
+false<br />\r
+ <span class=\r
+"hightlight">cluster.tmp.directory=/homes/clustengine/testoutput-</span>\r
+a directory to use for temporary files storage. The value must be\r
+an absolute path to the temporary directory. Required. The value\r
+must be different from what is defined for local engine. This\r
+directory must be accessible from all cluster nodes.<br />\r
+ For the cluster engine to work, the SGE_ROOT and LD_LIBRARY_PATH\r
+environment variables have to be defined. They tell the cluster\r
+engine where to find DRMAA libraries. These variables\r
+should be defined when the web application server starts up, e.g.</p>\r
+\r
+<p><span class="code">SGE_ROOT=/gridware/sge<br />\r
+ LD_LIBRARY_PATH=/gridware/sge/lib/lx24-amd64</span></p>\r
+\r
+<p>Finally, do not forget to configure executables for the cluster\r
+execution, they may be the same as for the local execution but may\r
+be different. Please refer to the executable configuration section\r
+for further details.</p>\r
+\r
+<h3><a name="exec" id="exec"></a>Executable Configuration</h3>\r
+\r
+<p>All the executable programs\r
+are configured in <span class="hightlight">conf/Executable.properties</span> file. Each executable\r
+is configured with a number of options. They are: <span class=\r
+"code">local.X.bin.windows=&lt;path to executable under windows\r
+system, optional&gt;<br />\r
+ local.X.bin=&lt;path to the executable under non-windows system,\r
+optional&gt;<br />\r
+ cluster.X.bin=&lt;path to the executable on the cluster, all\r
+cluster nodes must see it, optional&gt;<br />\r
+ X.bin.env=&lt;semicolon separated list of environment variables\r
+for executable, use hash symbol as name value separator,\r
+optional&gt;<br />\r
+ X.--aamatrix.path=&lt;path to the directory containing\r
+substitution matrices, optional&gt;<br />\r
+ X.presets.file=&lt;path to the preset configuration file, optional\r
+&gt;<br />\r
+ X.parameters.file=&lt;path to the parameters configuration file,\r
+optional&gt;<br />\r
+ X.limits.file=&lt;path to the limits configuration file,\r
+optional&gt;<br />\r
+ X.cluster.settings=&lt;list of the cluster specific options,\r
+optional&gt;</span></p>\r
+\r
+<p>Where X is either  clustal, muscle, mafft, probcons or tcoffee. </p>\r
+\r
+<p>Default JABAWS configuration includes path to local executables\r
+to be run by the local engine only, all cluster related settings\r
+are commented out, but they are there for you as example. Cluster\r
+engine is disabled by default. To configure executable for cluster\r
+execution un comment the X.cluster settings and change them\r
+appropriately. </p>\r
+<p>By default limits are set well in excess of what you may want to offer to the users outside your lab, to make sure that the tasks are never rejected. The default limit is 100000 sequences of 100000 letters on average for all of the JABA web services.  You can adjust the limits according to your needs by editing <span class="hightlight">conf/settings/&lt;X&gt;Limit.xml</span> files.<br />\r
+  After you have completed the editing your configuration may look like\r
+  this:<span class="code">local.mafft.bin.windows=<br />\r
+    local.mafft.bin=binaries/mafft<br />\r
+    cluster.mafft.bin=/homes/cengine/mafft<br />\r
+    mafft.bin.env=MAFFT_BINARIES#/homes/cengine/mafft;FASTA_4_MAFFT#/bin/fasta34;<br />\r
+    mafft.--aamatrix.path=binaries/matrices<br />\r
+    mafft.presets.file=conf/settings/MafftPresets.xml<br />\r
+    mafft.parameters.file=conf/settings/MafftParameters.xml<br />\r
+    mafft.limits.file=conf/settings/MafftLimits.xml<br />\r
+    mafft.cluster.settings=-q bigmem.q -l h_cpu=24:00:00 -l\r
+    h_vmem=6000M -l ram=6000M</span></p>\r
+<p>Please not that relative paths must only be specified for the\r
+files that reside inside web application directory, all other paths\r
+must be supplied as absolute!</p>\r
+\r
+<p>Furthermore, you should avoid using environment variables within the paths or options - since these will not be evaluated correctly.  Instead, please explicitly\r
+specify the absolute path to anything\r
+normally evaluated from an environment variable at execution time.</p>\r
+\r
+<p>If you are using JABAWS to submit jobs to the cluster (with\r
+cluster engine enabled), executables must be available from all\r
+cluster nodes the task can be sent to, also paths to the\r
+executables on the cluster e.g. <span class=\r
+"hightlight">cluster.&lt;exec_name&gt;.bin</span> must be\r
+absolute.</p>\r
+\r
+<p>Executables can be located anywhere in your system, they do not\r
+have to reside on the server as long as the web application server\r
+can access and execute them.</p>\r
+\r
+<p>Cluster settings are treated as a black box, the system will\r
+just pass whatever is specified in this line directly to the\r
+cluster submission library. This is how DRMAA itself treats this\r
+settings. More exactly DRMAA <span class="hightlight">JobTemplate.setNativeSpecification()</span> function will be called.</p>\r
+\r
+<h3><a name="setexecenv" />Defining Environment Variables for\r
+Executables</h3>\r
+\r
+<p>Environment variables can be defined in property <span class=\r
+"code">x.bin.env</span> Where <span class="hightlight">x</span> is\r
+one of five executables supported by JABAWS. Several environment\r
+variables can be specified in the same line. For example.<br />\r
+ <span class=\r
+"code">mafft.bin.env=MAFFT_BINARIES#/homes/cengine/mafft;FASTA_4_MAFFT#/bin/fasta34;</span></p>\r
+\r
+<p>The example above defines two environment variables with names\r
+MAFFT-BINARIES and FASTA_4_MAFFT and values /homes/cengine/mafft\r
+and /bin/fasta34 respectively. Semicolon is used as a separator\r
+between different environment variables whereas hash is used as a\r
+separator for name and value of the variable.</p>\r
+\r
+<h3><a name="mafftconf" id="mafftconf"></a>Configure JABAWS to Work\r
+with Mafft</h3>\r
+\r
+<p>If you use default configuration you do not need to read any\r
+further. The default configuration will work for you without any\r
+changes, however, if you want to install Mafft yourself then there\r
+is a couple of more steps to do.</p>\r
+\r
+<p>Mafft executable needs to know the location of other files\r
+supplied with Mafft. In addition some Mafft functions depends on\r
+the fasta executable, which is not supplied with Mafft, but is a\r
+separate package. Mafft needs to know the location of fasta34\r
+executable.</p>\r
+\r
+<p>To let Mafft know where the other files from its package are\r
+change the value of MAFFT-BINARIES environment variables. To let\r
+Mafft know where is the fasta34 executable set the value of\r
+FASTA_4_MAFFT environment variable to point to a location of\r
+fasta34 program. The latter can be added to the PATH variable\r
+instead. If you are using executables supplied with JABAWS, the\r
+path to Mafft binaries would be like <span class=\r
+"hightlight">&lt;relative path to web application\r
+directory&gt;/binaries/src/mafft/binaries</span> and the path to\r
+fasta34 binary would be <span class="hightlight">&lt;relative path\r
+to web application\r
+directory&gt;/binaries/src/fasta34/fasta34</span>. You can specify\r
+the location of Mafft binaries as well as fasta34 program elsewhere\r
+by providing an absolute path to them. All these settings are\r
+defined in <span class=\r
+"hightlight">conf/Executable.properties</span> file.</p>\r
+<h3><a name="settinglimit" id="settinglimit"></a>Limiting the size of the job accepted by JABAWS </h3>\r
+<p>JABAWS can be configured to reject excessively large tasks.  This is useful if you operate JABAWS service for many users. By defining a  maximum allowed task size you can provide an even service for all users and  prevents waist of resources on the tasks too large to complete  successfully. You can define the maximum number of sequences and the maximum average  sequence length that JABAWS accepts for each JABA Web Service independently. \r
+Furthermore, you can define different limits for different  presets of the same web service. <br />\r
+By default limits are set well in excess of what you may  want to offer to the users outside your lab, to make sure that the tasks are  never rejected. The default limit is 100000 sequences of 100000 letters on  average for all of the JABA web services. You can adjust the limits according  to your needs by editing <span class="hightlight">conf/settings/&lt;X&gt;Limit.xml</span> files.</p>\r
+<h3><a name="diffbin" id="diffbin"></a>Using a different version of the alignment program with JABAWS</h3>\r
+<p>JABAWS supplied with binaries and source code of the executables which version it supports. So normally you would not need to install your own executables. However, if you have a different version of an executable (e.g. an alignment program) which you prefer, you could use it as long as it supports all the functions JABAWS executable supported. This could be the case with more recent executable. If the options supported by your chosen executable is different when the standard JABAWS executable, than you need to edit <em>ExecutableName</em>Paramaters.xml&nbsp; configuration file. </p>\r
+<h3><a name="mixuse" id="mixuse"></a>Load balancing </h3>\r
+<p>If your cluster is busy and have significant waiting times you can achieve a faster response by allowing the server machine to calculate small tasks and the reserve the cluster for bigger jobs. This works especially well if your server is a powerful machine with many CPUs. To do this you need to enable and configure both the cluster and the local engines. Once this is done decide on the maximum size of a task to be run on the server locally. Then, edit <span class="hightlight">&quot;# LocalEngineExecutionLimit #&quot; </span>preset in<span class="hightlight"> &lt;ServiceName&gt;Limits.xml</span> file accordingly. JABAWS server then will balance the load according to the following rule: If the task size is smaller then the maximum task size for local engine, and the local engine has idle threads, then calculate task locally otherwise submit the task to the cluster. </p>\r
+<h3><a name="confaccessright" id="confaccessright"></a>Reviewing JABAWS configuration via web browser</h3>\r
+<p>Access to configuration files is prohibited to any unauthorized users by means of security constrain defined in web application descriptor file. There is a special user role called <span class="hightlight">admin</span> who can access these files. This comes handy if you would like to keep an eye on any of the task outputs stored in jobsout, or would like to view the configuration files. To access the configuration files add admin user into your application server. The way you do it  depends on where you would like the user passwords to come from and your web application server. If you use Tomcat, then the simplest way is to use Tomcat Memory Realm which is linked to a plain text configuration file. To define the user in Tomcat server add an entry in <span class="hightlight">conf/tomcat-user.xml</span> file. <span class="code">&lt;role rolename=&quot;admin&quot;/&gt;<br />\r
+  &lt;user username=&quot;admin&quot; password=&quot;your password here &quot; roles=&quot;admin&quot;/&gt;</span></p>\r
+<p>Once this is done make sure the servlet that returns the web application directory listings is enabled. Look in the <span class="hightlight">&lt;tomcatroot&gt;/conf/web.xml</span> file for the following <span class="code">&lt;param-name&gt;listings&lt;/param-name&gt;<br />\r
+  &lt;param-value&gt;true&lt;/param-value&gt;</span></p>\r
+<p>The whole section that defines default listing servlet is below</p>\r
+<p class="code"> &lt;servlet&gt;<br />\r
+  &lt;servlet-name&gt;default&lt;/servlet-name&gt;<br />\r
+  &lt;servlet-class&gt;org.apache.catalina.servlets.DefaultServlet&lt;/servlet-class&gt;<br />\r
+  &lt;init-param&gt;<br />\r
+  &lt;param-name&gt;debug&lt;/param-name&gt;<br />\r
+  &lt;param-value&gt;0&lt;/param-value&gt;<br />\r
+  &lt;/init-param&gt;<br />\r
+  &lt;init-param&gt;<br />\r
+  &lt;param-name&gt;listings&lt;/param-name&gt;<br />\r
+  &lt;param-value&gt;true&lt;/param-value&gt;<br />\r
+  &lt;/init-param&gt;<br />\r
+  &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br />\r
+  &lt;/servlet&gt;<br />\r
+</p>\r
+<p>These listings are read only by default.</p>\r
+<h3><a name="testingJaba" id="testingJaba"></a>Testing JABA Web Services</h3>\r
+<p>You can use a command line client (part of the client only\r
+  package) to test your JABAWS installation as described <a href="man_client.html">here</a>. If you downloaded a JABAWS\r
+  server package, you can use <span class=\r
+"hightlight">&lt;your_jaba_context_name&gt;/WEB-INF/lib/jaba-client.jar</span> to test JABAWS installation as described in <a href=\r
+"man_serverwar.html#usingWsTester">here</a>. If you downloaded the source\r
+  code, then you could run a number of test suits defined in the\r
+  build.xml Apache Ant  file.</p>\r
+<h3><a name="logs" id="logs"></a>JABAWS requests logging </h3>\r
+<p>Enable Tomcat log valve. To do this uncomment the following section of <span class="hightlight">&lt;tomcat_root&gt;/conf/server.xml</span> configuration file. </p>\r
+<p class="code"> &lt;Valve className=&quot;org.apache.catalina.valves.AccessLogValve&quot; directory=&quot;logs&quot; <br />\r
+  prefix=&quot;localhost_access_log.&quot; suffix=&quot;.txt&quot; pattern=&quot;common&quot; resolveHosts=&quot;false&quot;/&gt;</p>\r
+<p> The following information will be logged:</p>\r
+<table width="100%" border="0" style="margin:0">\r
+  <tr>\r
+    <th>Remote IP</th>\r
+    <th>Date</th>\r
+    <th>Method server_URL protocol </th>\r
+    <th>HTTP status </th>\r
+    <th>Response size in bytes </th>\r
+  </tr>\r
+  <tr>\r
+    <td>10.31.11.159</td>\r
+    <td>[10/Feb/2010:16:51:32 +0000]</td>\r
+    <td>&quot;POST /jws2/MafftWS HTTP/1.1&quot;</td>\r
+    <td>200</td>\r
+    <td>2067</td>\r
+  </tr>\r
+</table>\r
+<p>Which can be processed in various programs for log analysis , such as <a href="http://www.webalizer.org/">WebAlizer</a>, <a href="http://www.analog.cx/">Analog</a>, <a href="http://awstats.sourceforge.net/">AWStats</a>. </p>\r
+<h3><a name="logfiles" id="logfiles"></a>JABAWS internal logging </h3>\r
+<p>JABAWS can be configured to log what it is doing. This comes\r
+  handy if you would like to see who is using your web services or\r
+  need to chase some problems. JABAWS uses <a href=\r
+"http://logging.apache.org/log4j/1.2/">log4j</a> to do the logging,\r
+  the example of log4j configuration is bundled with JABAWS war file.\r
+  You will find it in the <span class=\r
+"hightlight">/WEB-INF/classes/log4j.properties</span> file. All the\r
+  lines in this file are commented out. The reason why the logging is\r
+  disabled by default it simple, log4j have to know the exact\r
+  location where the log files should be stored. This is not known up\r
+  until the deployment time. To enable the logging you need to\r
+  define<span class="hightlight"> logDir</span> property in the <span\r
+class="hightlight">log4j.properties</span> and uncomment section of\r
+  the file which corresponds to your need. More information is given\r
+  in the <span class="hightlight">log4j.properties</span> file\r
+  itself. Restart the Tomcat or the JABAWS web application to apply\r
+  the settings.</p>\r
+<p>After you have done this, assuming that you did not change the\r
+  log4j.properties file yourself, you should see the application log\r
+  file called <span class="hightlight">activity.log</span>. The\r
+  amount of information logged can be adjusted using different\r
+  logging levels, it is reduced in the following order of log levels\r
+  TRACE, DEBUG, INFO, WARN, ERROR, FATAL.</p>\r
+<p>If you would like to know who is using your services, you might\r
+  want to <a href="#logs">enable Tomcat request\r
+    logging</a>.</p>\r
+<h3><a name="execstat" id="execstat"></a>Monitoring JABAWS</h3>\r
+<p>JABAWS stores cluster task ids for all tasks which were run on the cluster. Using cluster ids the detailed statistics can be extracted from cluster accounting system. Due to the fact that each cluster supported by JABAWS have different accounting system it was not possible to provide ready to use statistics. <br />\r
+  For the local execution the starting and finishing time in nano seconds can be found in STARTED and FINISHED files respectively. In time we will provide the tools to extract execution time statistics, so keep the content of your working directory ready!</p>\r
+<h3><a name="warfile" id="warfile"></a>JABAWS War File Content</h3>\r
+<table width="100%">\r
+  <tr>\r
+    <th style="width:19%">Directory</th>\r
+    <th style="width:81%">Content description</th>\r
+  </tr>\r
+  <tr>\r
+    <td>conf/</td>\r
+    <td>contains configuration files such as Executable.properties,\r
+      Engine.local.properties, Engine.cluster.properties</td>\r
+  </tr>\r
+  <tr>\r
+    <td>conf/settings</td>\r
+    <td>Contains individual executable description files. In particular\r
+      XXXParameters.xml, XXXPresets.xml, XXXLimits.xml where XXX is the\r
+      name of the executable</td>\r
+  </tr>\r
+  <tr>\r
+    <td>jobsout/</td>\r
+    <td>Contains directories generated when running an individual executable. E.g. input and output files and some other task\r
+      related data. (optional)</td>\r
+  </tr>\r
+  <tr>\r
+    <td>binaries/</td>\r
+    <td>Directory contains native executables - programs,\r
+      windows binaries (optional)</td>\r
+  </tr>\r
+  <tr>\r
+    <td>binaries/src</td>\r
+    <td>Contains source of native executables and Linux i386\r
+      binaries.</td>\r
+  </tr>\r
+  <tr>\r
+    <td>binaries/matrices</td>\r
+    <td>Substitution matrices\r
+      <!-- what format ? --></td>\r
+  </tr>\r
+  <tr>\r
+    <td>WEB-INF</td>\r
+    <td>Web application descriptor</td>\r
+  </tr>\r
+  <tr>\r
+    <td>WEB-INF/lib</td>\r
+    <td>Web application libraries</td>\r
+  </tr>\r
+  <tr>\r
+    <td>WEB-INF/classes</td>\r
+    <td>log4j.properties - log configuration file (optional)</td>\r
+  </tr>\r
+  <tr>\r
+    <td colspan="2"><strong>Help Pages</strong> </td>\r
+  </tr>\r
+  <tr>\r
+    <td>/</td>\r
+    <td>help pages, index.html is the starting page</td>\r
+  </tr>\r
+  <tr>\r
+    <td>dm_javadoc</td>\r
+    <td>javadoc for JABAWS client (the link is available from How To\r
+      pages)</td>\r
+  </tr>\r
+  <tr>\r
+    <td>prog_docs</td>\r
+    <td>documentation for programs that JABAWS uses</td>\r
+  </tr>\r
+  <tr>\r
+    <td>images</td>\r
+    <td>images referenced by html pages</td>\r
+  </tr>\r
+</table>\r
+<p>&nbsp;</p>\r
+</div>\r
+<!-- content end-->\r
+<div id="copyright">Last update: 1 April 2011<br />\r
+ Peter Troshin, Jim Procter and Geoff Barton, The Barton Group, University of\r
+Dundee, UK</div>\r
+</div>\r
+\r
+<!-- wrapper end-->\r
+</div>\r
+<!-- page end-->\r
+\r
+<!-- Google analitics -->\r
+<script type="text/javascript">\r
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");\r
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));\r
+</script>\r
+<script type="text/javascript">\r
+try{\r
+var pageTracker = _gat._getTracker("UA-5356328-1");\r
+pageTracker._trackPageview();\r
+} catch(err) {}\r
+</script>\r
+</body>\r
+</html>\r
+\r
diff --git a/website/man_dev.html b/website/man_dev.html
new file mode 100644 (file)
index 0000000..73dee08
--- /dev/null
@@ -0,0 +1,359 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "XHTML 1.0 Strict"\r
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<meta name="Last-modified" content="Mon, 4 Apr 2011 12:00:00 GMT"/>\r
+<title>Java Bioinformatics Analyses Web Services (JABAWS) client developers manual</title>\r
+<link href="ws.css" rel="stylesheet" type="text/css" media=\r
+"screen, projection, handheld, tv" />\r
+<link rel="stylesheet" type="text/css" media="print" href=\r
+"print.css" />\r
+<script type="text/javascript" src="prototype-1.6.0.3.js"></script>\r
+</head>\r
+<body>\r
+<div id="page">\r
+<div id="banner">\r
+<table> \r
+<tr><td style="width:130px;"><a href="http://www.dundee.ac.uk"><img src="images/uod_lt.gif"  alt="University of Dundee" class="logo"  title="University of Dundee" longdesc="http://www.dundee.ac.uk"/></a></td>\r
+<td class="bg"><img src="images/jabaws.png" title="JABAWS:MSA" alt="JABAWS:MSA"/></td>\r
+<td class="bg"><img src="images/align.png"/></td>\r
+</tr>\r
+</table></div><!-- banner end-->\r
+\r
+<div id="wrapper">\r
+<div id="panel"><a href="index.html">Home</a> \r
+ <a href="quick_start.html">Getting Started</a> \r
+ <a class="selected" href="man_about.html">Manual</a> \r
+       <div id="submenu">\r
+               <a href="man_about.html">About</a>\r
+               <a href="man_servervm.html" title="JABAWS Server as Virtual Appliance">Server VA</a>\r
+               <a href="man_serverwar.html" title="JABAWS Server as Web Application aRchive">Server WAR</a>\r
+               <a href="man_configuration.html" >Server<br/>\r
+               Configuration</a>\r
+               <a href="man_client.html" title="JABAWS Command Line Client">CMD Client</a>\r
+               <a class="selected" href="man_dev.html" title="Accessing JABAWS from your program">Accessing<br/>\r
+               JABAWS</a>      \r
+       </div>\r
+<a href="download.html">Download</a> \r
+<a href="contacts.html">Contact Us</a>\r
+<a href="http://www.compbio.dundee.ac.uk">Barton Group</a> \r
+</div>\r
+\r
+<!-- panel end-->\r
+<div id="content">\r
+<h2 id="headtitle">JABAWS MANUAL</h2>\r
+\r
+<h2>Using JABAWS From Your Program </h2>\r
+<ul>\r
+  <li><a href="#wsfunctions">Web services functions overview </a></li>\r
+  <li><a href="#templatestr">The template client structure</a></li>\r
+  <li><a href="#connectto">Connecting to JABAWS</a></li>\r
+  <li><a href="#validnames">Valid JABAWS service names and WSDL files</a></li>\r
+  <li><a href="#defalign">Aligning sequences</a></li>\r
+  <li><a href="#checkresults">Checking the status of the calculation </a></li>\r
+  <li><a href="#presetalign">Aligning with presets</a></li>\r
+  <li><a href="#customalign">Aligning with custom parameters</a></li>\r
+  <li><a href="#writingaltofile">Writing alignments to a file</a></li>\r
+  <li><a href="#compex">A complete client example </a></li>\r
+  <li><a href="#buildart">Building web services artifacts</a></li>\r
+</ul>\r
+<h3><a name="wsfunctions" id="wsfunctions"></a>Web services functions overview </h3>\r
+<p>All JABA multiple sequence alignment web services comply to the same interface, thus the function described below are available from all the services. </p>\r
+<p><strong>Functions for initiating the alignment </strong><span class="code">  String id = align(List&lt;FastaSequence&gt; list)<br />\r
+  String id = customAlign(List&lt;FastaSequence&gt; sequenceList, List&lt;Option&gt; optionList)<br />\r
+  String id = presetAlign(List&lt;FastaSequence&gt; sequenceList, Preset preset)</span></p>\r
+<p><strong>Functions pertaining to job monitoring and control</strong><br />\r
+  <span class="code">JobStatus status = getJobStatus(String id)<br />\r
+  Alignment al = getResult(String id)<br />\r
+  boolean cancelled = cancelJob(String id)<br />\r
+  ChunkHolder chunk = pullExecStatistics(String id, long marker)</span></p>\r
+<p><strong>Functions relating to service features discovery</strong><br />\r
+  <span class="code">RunnerConfig rc = getRunnerOptions()<br />\r
+  Limit limit = getLimit(String name)<br />\r
+  LimitsManager lm = getLimits()<br />\r
+  PresetManager pm = getPresets()</span></p>\r
+<p>Please refer to a <a href="dm_javadoc/compbio/data/msa/MsaWS.html">data model  javadoc</a> for a detailed description of each methods. </p>\r
+<h3><a name="templatestr" id="templatestr"></a>Structure of the template command line client</h3>\r
+<table width="100%" border="1">\r
+  <tr>\r
+    <td style="width:19%"><strong>Packages</strong></td>\r
+    <td style="width:81%"><strong>Classes and Interfaces </strong></td>\r
+  </tr>\r
+  <tr>\r
+    <td>compbio.data.msa </td>\r
+    <td>MsaWS the interface for all multiple sequence alignment web services </td>\r
+  </tr>\r
+  <tr>\r
+    <td>compbio.data.sequence</td>\r
+    <td>JABAWS data types </td>\r
+  </tr>\r
+  <tr>\r
+    <td>compbio.metadata</td>\r
+    <td>JABAWS meta data types </td>\r
+  </tr>\r
+  <tr>\r
+    <td>compbio.ws.client</td>\r
+    <td>JABAWS command line client </td>\r
+  </tr>\r
+</table>\r
+<p>Additional utility libraries this client depend upon is the compbio-util-1.3.jar and compbio-annotation-1.0.jar. <br />\r
+  Please refer to a <a href="dm_javadoc/index.html">data model javadoc</a> for a detailed description of each class and its methods. </p>\r
+<h3><a name="connectto" id="connectto"></a>Connecting to JABAWS</h3>\r
+<p class="attention">For a complete working example of JABAWS command line client please see compbio.ws.client.Jws2Client class. JABAWS command line client source code is available from the <a href="download.html">download page</a>. Please note that for now all the examples are in Java other languages will follow given a sufficient demand. </p>\r
+<p>Download a binary JABAWS client. Add the client to the class path. The following code excerpt will connect your program to Clustal web service deployed in the University of Dundee. </p>\r
+<p class="code"> import java.net.URL;<br />\r
+  import javax.xml.namespace.QName;<br />\r
+  import javax.xml.ws.Service;<br />\r
+  ...............<br />\r
+  1) String qualifiedName = &quot;http://msa.data.compbio/01/01/2010/&quot;;<br />\r
+  2) URL url = new URL(&quot;http://www.compbio.dundee.ac.uk/jabaws/ClustalWS?wsdl&quot;);<br />\r
+  3) QName qname = new QName(, &quot;ClustalWS&quot;);<br />\r
+  4) Service serv = Service.create(url, qname);<br />\r
+  5) MsaWS msaws = serv.getPort(new QName(qualifiedName, &quot;ClustalWSPort&quot;),\r
+  MsaWS.class);</p>\r
+<p>Line 1 makes a qualified name for JABA web services.<br />\r
+  Line 2 \r
+  constructs the URL to the web services WSDL. <br />\r
+  Line 3 makes a qualified name instance for Clustal JABA web service. <br />\r
+  Line 4 creates a service instance.<br />\r
+  Line 5 makes a connection to the server. </p>\r
+<p>A more generic connection method would look like this </p>\r
+<p class="code"> import java.net.URL;<br />\r
+  import javax.xml.namespace.QName;<br />\r
+  import javax.xml.ws.Service;<br />\r
+  import compbio.ws.client.Services<br />\r
+  .............. <br />\r
+  String qualifiedServiceName = &quot;http://msa.data.compbio/01/01/2010/&quot;;<br />\r
+  String host = &quot;http://www.compbio.dundee.ac.uk/jabaws&quot;;<br />\r
+  // In real life the service name can come from args<br />\r
+  Services clustal = Services.ClustalWS;<br />\r
+  URL url = new URL(host + &quot;/&quot; + clustal.toString() + &quot;?wsdl&quot;);<br />\r
+  QName qname = new QName(qualifiedServiceName, clustal.toString());<br />\r
+  Service serv = Service.create(url, qname);<br />\r
+  MsaWS msaws = serv.getPort(new QName(qualifiedServiceName, clustal<br />\r
+  + &quot;Port&quot;), MsaWS.class);</p>\r
+<p>Where Services is enumeration of JABAWS web services. All JABAWS multiple sequence alignment methods confirm to MsaWS specification, thus from the caller point of view all JABAWS web services can be represented by MsaWS interface. The full documentation of MsaWS functions is available from the <a href="dm_javadoc/compbio/data/msa/MsaWS.html">javadoc</a>. </p>\r
+<h3><a name="validnames" id="validnames"></a>Valid JABAWS service names and WSDL files </h3>\r
+<ul>\r
+  <li><a href="http://www.compbio.dundee.ac.uk/jabaws/ClustalWS?wsdl">ClustalWS</a> (http://www.compbio.dundee.ac.uk/jabaws/ClustalWS?wsdl) </li>\r
+  <li><a href="http://www.compbio.dundee.ac.uk/jabaws/MuscleWS?wsdl">MuscleWS</a> (http://www.compbio.dundee.ac.uk/jabaws/MuscleWS?wsdl) </li>\r
+  <li><a href="http://www.compbio.dundee.ac.uk/jabaws/MafftWS?wsdl">MafftWS</a> (http://www.compbio.dundee.ac.uk/jabaws/MafftWS?wsdl) </li>\r
+  <li><a href="http://www.compbio.dundee.ac.uk/jabaws/TcoffeeWS?wsdl">TcoffeeWS</a> (http://www.compbio.dundee.ac.uk/jabaws/TcoffeeWS?wsdl) </li>\r
+  <li><a href="http://www.compbio.dundee.ac.uk/jabaws/ProbconsWS?wsdl">ProbconsWS</a> (http://www.compbio.dundee.ac.uk/jabaws/ProbconsWS?wsdl) </li>\r
+</ul>\r
+<h3><a name="defalign" id="defalign"></a>Aligning sequences </h3>\r
+<p>Given that <span class="hightlight">msaws</span> is web service proxy, created as described in &quot;Connecting to JABAWS&quot; section, the actual alignment can be obtained as follows: </p>\r
+<p class="code">1) List&lt;FastaSequence&gt; fastalist = SequenceUtil.readFasta(new FileInputStream(file));<br />\r
+  2) String jobId = msaws.align(fastalist); <br />\r
+  3) Alignment alignment = msaws.getResult(jobId);</p>\r
+<p>Line  one loads FASTA sequence from the file<br />\r
+  Line two submits them to web service represented by msaws proxy <br />\r
+  Line three retrieves the alignment from a web service. This line will block the execution until the result is available. Use this with caution. In general, you should make sure that the calculation has been completed before attempting retrieving results. This is to avoid keeping the connection to the server on hold for a prolonged periods of time. While this may be ok with your local server, our public server (<a href="http://www.compbio.dundee.ac.uk/jabaws">www.compbio.dundee.ac.uk/jabaws</a>) will not let you hold the connection for longer than 10 minutes. This is done to prevent excessive load on the server. The next section describes how to check the status of the calculation.<br />\r
+  Methods and classes mentioned in the excerpt are available from the JABAWS client library. </p>\r
+<h3><a name="checkresults" id="checkresults"></a>Checking the status of the calculation </h3>\r
+<p> You may have noticed that there was no pause between submitting the job and retrieving of the results. This is because <span class="hightlight">getResult(jobId)</span> method block the processing until the calculation is completed. However, taking into account that the connection holds server resources, our public server (<a href="http://www.compbio.dundee.ac.uk/jabaws">www.compbio.dundee.ac.uk/jabaws</a>) is configured to reset the connection after 10 minutes of waiting. To work around the connection reset you are encouraged to check whether the calculation has been completed before accessing the results.      You can do it like this: </p>\r
+<p> <span class="code">while (msaws.getJobStatus(jobId) != JobStatus.FINISHED) {<br />\r
+  &nbsp;&nbsp;&nbsp;&nbsp;Thread.sleep(2000); // wait two  seconds, then recheck the status <br />\r
+  }</span></p>\r
+<h3><a name="presetalign" id="presetalign"></a>Aligning with presets</h3>\r
+<p class="code">1) PresetManager presetman = msaws.getPresets();<br />\r
+  2) Preset preset = presetman.getPresetByName(presetName);<br />\r
+  3) List&lt;FastaSequence&gt; fastalist = SequenceUtil.readFasta(new FileInputStream(file));<br />\r
+  4) String jobId = msaws.presetAlign(fastalist, preset);<br />\r
+  5) Alignment alignment = msaws.getResult(jobId);</p>\r
+<p>Line one obtains the lists of presets supported by a web service.<br />\r
+  Line two return a particular Preset \r
+  by its name<br />\r
+  Lines three to five  are doing the same job as in the first <a href="#defalign"> aligning sequences example</a>.</p>\r
+<h3><a name="customalign" id="customalign"></a>Aligning with  custom parameters</h3>\r
+<p class="code"> 1) RunnerConfig options = msaws.getRunnerOptions();<br />\r
+  2) Argument matrix = options.getArgument(&quot;MATRIX&quot;);<br />\r
+  3) matrix.setValue(&quot;PAM300&quot;);<br />\r
+  4) Argument gapopenpenalty = options.getArgument(&quot;GAPOPEN&quot;);<br />\r
+  5) gapopenpenalty.setValue(&quot;20&quot;);<br />\r
+  6) List&lt;Argument&gt; arguments = new ArrayList&lt;Argument&gt;(); <br />\r
+  7) arguments.add(matrix);\r
+  arguments.add(gapopenpenalty);<br />\r
+  8) List&lt;FastaSequence&gt; fastalist = SequenceUtil.readFasta(new FileInputStream(file));<br />\r
+  9) String jobId = msaws.customAlign(fastalist, arguments);<br />\r
+  10) Alignment alignment = msaws.getResult(jobId);</p>\r
+<p>Line one obtains the <span class="hightlight">RunnerConfig</span> object that holds information on supported parameters and their values<br />\r
+  Line two retrieve a particular parameter from the holder by its name<br />\r
+  Lines three sets a value to this parameter which will be used in the calculation. <br />\r
+  Line four and five do the same but for another parameter<br />\r
+  Line 6 makes a List to hold the parameters <br />\r
+  Line seven puts the parameters into that list<br />\r
+  Line eight \r
+  and ten is the same as in previous examples<br />\r
+  Line nine submit an alignment request with the sequences and the parameters <br />\r
+  The names of all the parameters supported by a web service e.g. &quot;PAM300&quot; can be obtained using <span class="hightlight">options.getArguments() </span>method. Further details on the methods available from <span class="hightlight">RunnerConfig</span> object are available from the <a href="dm_javadoc/index.html">javadoc</a>. </p>\r
+<h3><a name="writingaltofile" id="writingaltofile"></a>Writing alignments to a file</h3>\r
+<p>There is a utility method in the client library that does exactly that. </p>\r
+<p> <span class="code">Alignment alignment = align(...) <br />\r
+  FileOutputStream outStream = new FileOutputStream(file);<br />\r
+  ClustalAlignmentUtil.writeClustalAlignment(outStream, align);</span></p>\r
+<h3><a name="compex" id="compex"></a>A complete client example </h3>\r
+<p>Finally, a complete example of the program that connects to JABAWS Clustal service and aligns sequences using one of the  Clustal web service preset. Three is also a <a href="Example_template.pdf">PDF version</a> of this example with syntax highlighted. The text comments are commented by block style comments e.g. /* comment */, the alternatives given in the code are line commented // comment. You may want to remove line style comments to test alternatives of the functions. All you need for this to work is a <a href="download.html">JABAWS binary client</a>. Please make sure that the client is in the Java class path before running this example.</p>\r
+<pre class="code" style="line-height:1em;">\r
+import java.io.ByteArrayInputStream;\r
+import java.io.FileNotFoundException;\r
+import java.io.IOException;\r
+import java.net.URL;\r
+import java.util.List;\r
+\r
+import javax.xml.namespace.QName;\r
+import javax.xml.ws.Service;\r
+\r
+import compbio.data.msa.MsaWS;\r
+import compbio.data.sequence.Alignment;\r
+import compbio.data.sequence.FastaSequence;\r
+import compbio.data.sequence.SequenceUtil;\r
+import compbio.metadata.JobSubmissionException;\r
+import compbio.metadata.LimitExceededException;\r
+import compbio.metadata.Preset;\r
+import compbio.metadata.PresetManager;\r
+import compbio.metadata.ResultNotAvailableException;\r
+import compbio.metadata.UnsupportedRuntimeException;\r
+import compbio.metadata.WrongParameterException;\r
+\r
+public class Example {\r
+\r
+       /*\r
+        * Input sequences for alignment\r
+        */\r
+       static final String input = &quot;&gt;Foo\r\n&quot;\r
+                       + &quot;MTADGPRELLQLRAAVRHRPQDFVAWLMLADAELGMGDTTAGEMAVQRGLALHPGHPEAVARLGR&quot;\r
+                       + &quot;VRWTQQRHAEAAVLLQQASDAAPEHPGIALWLGHALEDAGQAEAAAAAYTRAHQLLPEEPYITAQ&quot;\r
+                       + &quot;LLNWRRRLCDWRALDVLSAQVRAAVAQGVGAVEPFAFLSEDASAAEQLACARTRAQAIAASVRPL&quot;\r
+                       + &quot;APTRVRSKGPLRVGFVSNGFGAHPTGLLTVALFEALQRRQPDLQMHLFATSGDDGSTLRTRLAQA&quot;\r
+                       + &quot;STLHDVTALGHLATAKHIRHHGIDLLFDLRGWGGGGRPEVFALRPAPVQVNWLAYPGTSGAPWMD&quot;\r
+                       + &quot;YVLGDAFALPPALEPFYSEHVLRLQGAFQPSDTSRVVAEPPSRTQCGLPEQGVVLCCFNNSYKLN&quot;\r
+                       + &quot;PQSMARMLAVLREVPDSVLWLLSGPGEADARLRAFAHAQGVDAQRLVFMPKLPHPQYLARYRHAD&quot;\r
+                       + &quot;LFLDTHPYNAHTTASDALWTGCPVLTTPGETFAARVAGSLNHHLGLDEMNVADDAAFVAKAVALAS&quot;\r
+                       + &quot;DPAALTALHARVDVLRRESGVFEMDGFADDFGALLQALARRHGWLGI\r\n&quot;\r
+                       + &quot;\r\n&quot;\r
+                       + &quot;&gt;Bar\r\n&quot;\r
+                       + &quot;MGDTTAGEMAVQRGLALHQQRHAEAAVLLQQASDAAPEHPGIALWLHALEDAGQAEAAAAYTRAH&quot;\r
+                       + &quot;QLLPEEPYITAQLLNAVAQGVGAVEPFAFLSEDASAAESVRPLAPTRVRSKGPLRVGFVSNGFGA&quot;\r
+                       + &quot;HPTGLLTVALFEALQRRQPDLQMHLFATSGDDGSTLRTRLAQASTLHDVTALGHLATAKHIRHHG&quot;\r
+                       + &quot;IDLLFDLRGWGGGGRPEVFALRPAPVQVNWLAYPGTSGAPWMDYVLGDAFALPPALEPFYSEHVL&quot;\r
+                       + &quot;RLQGAFQPSDTSRVVAEPPSRTQCGLPEQGVVLCCFNNSYKLNPQSMARMLAVLREVPDSVLWLL&quot;\r
+                       + &quot;SGPGEADARLRAFAHAQGVDAQRLVFMPKLPHPQYLARYRHADLFLDTHPYNAHTTASDALWTGC&quot;\r
+                       + &quot;PVLTTPGETFAARVAGSLNHHLGLDEMNVADDAAFVAKAVALASDPAALTALHARVDVLRRESGV&quot;\r
+                       + &quot;FEMDGFADDFGALLQALARRHGWLGI\r\n&quot;\r
+                       + &quot;\r\n&quot;\r
+                       + &quot;&gt;Friends\r\n&quot;\r
+                       + &quot;MTADGPRELLQLRAAVRHRPQDVAWLMLADAELGMGDTTAGEMAVQRGLALHPGHPEAVARLGRV&quot;\r
+                       + &quot;RWTQQRHAEAAVLLQQASDAAPEHPGIALWLGHALEDHQLLPEEPYITAQLDVLSAQVRAAVAQG&quot;\r
+                       + &quot;VGAVEPFAFLSEDASAAEQLACARTRAQAIAASVRPLAPTRVRSKGPLRVGFVSNGFGAHPTGLL&quot;\r
+                       + &quot;TVALFEALQRRQPDLQMHLFATSGDDGSTLRTRLAQASTLHDVTALGHLATAKHIRHHGIDLLFD&quot;\r
+                       + &quot;LRGWGGGGRPEVFALRPAPVQVNWLAYPGTSGAPWMDYVLGDAFALPPALEPFYSEHVLRLQGAF&quot;\r
+                       + &quot;QPSDTSRVVAEPPSRTQCGLPEQGVVLCCFNNSYKLNPQSMARMLAVLREVPDSVLWLLSGPGEA&quot;\r
+                       + &quot;DARLRAFAHAQGVDAQRLVFMPKLPHPQYLARYRHADLFLDTHPYNAHTTASDALWTGCPVLTTP&quot;\r
+                       + &quot;GETFAARVAGSLNHHLGLDEMNVADDAAFVAKAVALASDPAALTALHARVDVLRRESI&quot;;\r
+\r
+       public static void main(String[] args) throws UnsupportedRuntimeException,\r
+                       LimitExceededException, JobSubmissionException,\r
+                       WrongParameterException, FileNotFoundException, IOException,\r
+                       ResultNotAvailableException, InterruptedException {\r
+\r
+               String qualifiedServiceName = &quot;http://msa.data.compbio/01/01/2010/&quot;;\r
+\r
+               /* Make a URL pointing to web service WSDL */\r
+               URL url = new URL(\r
+                               &quot;http://www.compbio.dundee.ac.uk/jabaws/ClustalWS?wsdl&quot;);\r
+\r
+               /*\r
+                * If you are making a client that connects to different web services\r
+                * you can use something like this:\r
+                */\r
+               // URL url = new URL(host + &quot;/&quot; + Services.ClustalWS.toString() +\r
+               // &quot;?wsdl&quot;);\r
+\r
+               QName qname = new QName(qualifiedServiceName, &quot;ClustalWS&quot;);\r
+               Service serv = Service.create(url, qname);\r
+               /*\r
+                * Multiple sequence alignment interface for Clustal web service\r
+                * instance\r
+                */\r
+               MsaWS msaws = serv.getPort(new QName(qualifiedServiceName, &quot;ClustalWS&quot;\r
+                               + &quot;Port&quot;), MsaWS.class);\r
+\r
+               /* Get the list of available presets */\r
+               PresetManager presetman = msaws.getPresets();\r
+\r
+               /* Get the Preset object by preset name */\r
+               Preset preset = presetman\r
+                               .getPresetByName(&quot;Disable gap weighting (Speed-oriented)&quot;);\r
+\r
+               /*\r
+                * Load sequences in FASTA format from the file You can use something\r
+                * like new FileInputStream(&lt;filename&gt;) to load sequence from the file\r
+                */\r
+               List&lt;FastaSequence&gt; fastalist = SequenceUtil\r
+                               .readFasta(new ByteArrayInputStream(input.getBytes()));\r
+\r
+               /*\r
+                * Submit loaded sequences for an alignment using preset. The job\r
+                * identifier is returned by this method, you can retrieve the results\r
+                * with it sometime later.\r
+                */\r
+               String jobId = msaws.presetAlign(fastalist, preset);\r
+\r
+               /* This method will block for the duration of the calculation */\r
+               Alignment alignment = msaws.getResult(jobId);\r
+\r
+               /*\r
+                * This is a better way of obtaining results, it does not involve\r
+                * holding the connection open for the duration of the calculation,\r
+                * Besides, as the University of Dundee public server will reset the\r
+                * connection after 10 minutes of idling, this is the only way to obtain\r
+                * the results of long running task from our public server.\r
+                */\r
+               // while (msaws.getJobStatus(jobId) != JobStatus.FINISHED) {\r
+               // Thread.sleep(1000); // wait a second, then recheck the status\r
+               // }\r
+\r
+               /* Output the alignment to standard out */\r
+               System.out.println(alignment);\r
+\r
+               // Alternatively, you can record retrieved alignment into the file in\r
+               // ClustalW format\r
+\r
+               // ClustalAlignmentUtil.writeClustalAlignment(new FileOutputStream(\r
+               // &quot;output.al&quot;), alignment);\r
+\r
+       }\r
+}\r
+</pre>\r
+For a more detailed description of all available types and their functions please refer to the <a href="dm_javadoc/index.html">data model javadoc</a>.\r
+<h3><a name="buildart" id="buildart"></a>Building web services artifacts</h3>\r
+<p>JABAWS are the standard <a href="http://jax-ws.java.net/">JAX-WS</a> SOAP web services, which are <a href="http://www.ws-i.org/">WS-I</a> basic   profile compatible. This means that you could use whatever tool your language has to work with web services. Below is how you can generate portable artifacts to work with JABAWS from Java. However,  if programming in Java we recommend using our  client library as it provides a handful of useful methods in addition to plain data types. </p>\r
+<p class="code">wsimport -keep http://www.compbio.dundee.ac.uk/jabaws/ClustalWS?wsdl</p>\r
+</div>\r
+\r
+<!-- content end-->\r
+<div id="copyright">Last update: 1 April 2011<br />\r
+ Peter Troshin, Jim Procter and Geoff Barton, The Barton Group, University of\r
+Dundee, UK</div>\r
+</div>\r
+\r
+<!-- wrapper end-->\r
+</div>\r
+<!-- page end-->\r
+\r
+<!-- Google analitics -->\r
+<script type="text/javascript">\r
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");\r
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));\r
+</script>\r
+<script type="text/javascript">\r
+try{\r
+var pageTracker = _gat._getTracker("UA-5356328-1");\r
+pageTracker._trackPageview();\r
+} catch(err) {}\r
+</script>\r
+</body>\r
+</html>\r
+\r
diff --git a/website/man_servervm.html b/website/man_servervm.html
new file mode 100644 (file)
index 0000000..66fc6c4
--- /dev/null
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "XHTML 1.0 Strict"\r
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<meta name="Last-modified" content="Mon, 4 Apr 2011 12:00:00 GMT"/>\r
+<title>Java Bioinformatics Analyses Web Services (JABAWS) Server Virtual Appliance Manual</title>\r
+<link href="ws.css" rel="stylesheet" type="text/css" media=\r
+"screen, projection, handheld, tv" />\r
+<link rel="stylesheet" type="text/css" media="print" href=\r
+"print.css" />\r
+<script type="text/javascript" src="prototype-1.6.0.3.js"></script>\r
+</head>\r
+<body>\r
+<div id="page">\r
+<div id="banner">\r
+<table> \r
+<tr><td style="width:130px;"><a href="http://www.dundee.ac.uk"><img src="images/uod_lt.gif"  alt="University of Dundee" class="logo"  title="University of Dundee" longdesc="http://www.dundee.ac.uk"/></a></td>\r
+<td class="bg"><img src="images/jabaws.png" title="JABAWS:MSA" alt="JABAWS:MSA"/></td>\r
+<td class="bg"><img src="images/align.png"/></td>\r
+</tr>\r
+</table></div><!-- banner end-->\r
+\r
+<div id="wrapper">\r
+<div id="panel"><a href="index.html">Home</a> \r
+ <a href="quick_start.html">Getting Started</a> \r
+ <a class="selected" href="man_about.html">Manual</a> \r
+       <div id="submenu">\r
+               <a href="man_about.html">About</a>\r
+               <a class="selected" href="man_servervm.html" title="JABAWS Server as Virtual Appliance">Server VA</a>\r
+               <a href="man_serverwar.html" title="JABAWS Server as Web Application aRchive">Server WAR</a>\r
+               <a href="man_configuration.html" >Server<br/>\r
+               Configuration</a>\r
+               <a href="man_client.html" title="JABAWS Command Line Client">CMD Client</a>\r
+               <a href="man_dev.html" title="Accessing JABAWS from your program">Accessing<br/>\r
+               JABAWS</a>      \r
+       </div>\r
+<a href="download.html">Download</a> \r
+<a href="contacts.html">Contact Us</a>\r
+<a href="http://www.compbio.dundee.ac.uk">Barton Group</a> \r
+</div>\r
+\r
+<!-- panel end-->\r
+<div id="content">\r
+<h2 id="headtitle">JABAWS MANUAL</h2>\r
+\r
+<h2>JABAWS Server Virtual Appliance</h2>\r
+<ul>\r
+    <li><a href="#whatisvm">What is JABAWS Virtual Appliance?</a></li>\r
+    <li><a href="#whenvm">When to use virtual appliance</a> </li>\r
+    <li><a href="#howtoinstallvm">How to install VMWare Player or VirtualBox</a></li>\r
+       <li><a href="#vmplayer">VMware Player appliance configuration </a></li>\r
+       <li><a href="#virtualbox">VirtualBox appliance configuration</a></li>\r
+       <li><a href="#jabawsAppliance">JABAWS Appliance details </a></li>\r
+    <li><a href="#jalviewWithJaba">Configuring Jalview to work with your JABAWS VM</a></li>\r
+    <li><a href="#vmiaccess">VM Network Settings </a></li>\r
+    </ul>\r
+\r
+<p><strong>Troubleshooting</strong></p>\r
+<ul>\r
+  <li><a href="#vmbexc"> VirtualBox fails to open the VM due to VERR_VMX_MSR_LOCKED_OR_DISABLED exception</a></li>\r
+  <li><a href="#vboxinvalidstate">VirtualBox 4.0 fails to import the VM due to VBOX_E_INVALID_OBJECT_STATE exception </a></li>\r
+  <li><a href="#ovfOnVmware">VMWare Player fails to open the VM with &quot;Fail to query source for information&quot; exception</a></li>\r
+</ul>\r
+<h3><a name="whatisvm" id="whatisvm"></a>What is the JABAWS Server Virtual Appliance?</h3>\r
+<p>The JABAWS <a href="http://en.wikipedia.org/wiki/Virtual_appliance">Virtual Appliance</a> is a \r
+way to run JABAWS server locally without the need to connect to the internet or configure JABAWS. \r
+What the appliance provides is a 'virtual server machine' (or more simply - virtual machine or VM), running an installation of the JABAWS \r
+Web Application Archive (WAR) on TurnKey Linux. Once this has started up, it displays a message indicating the IP address of the JABAWS server, allowing any JABAWS client (such as Jalview or the JABAWS command line client) to connect to it.<br/>\r
+You can run the appliance with freely available programs such as <a href="http://www.vmware.com/products/player">VMWare Player</a> or \r
+<a href="http://www.virtualbox.org/wiki/Download_Old_Builds_3_2">Oracle VirtualBox 3.2.x</a>, but you will need to install them first. We have tested the JABAWS appliance \r
+with VMware Player v 3.1.2 on Windows and Linux, and <a href="http://www.virtualbox.org/wiki/Download_Old_Builds_3_2">VirtualBox </a> v. 3.2.12 on Windows, Linux and Mac. \r
+  However, you are not limited to these virtualization systems and can use the JABAWS appliance with any commercial alternative. </p>\r
+<h3><a name="whenvm" id="whenvm"/></a>When to use the JABAWS Virtual Appliance</h3>\r
+<p>The appliance best suits users who would like to use the JABA web services locally. This might be because they do want to access \r
+systems over an internet or local intranet connection, or alternately, want to keep their data private. It is also \r
+the recommended option for users who want to install JABAWS on Windows, which does not support all the bioinformatics programs that JABAWS can run. \r
+<br/>Since the appliance is a self contained unit of software, it is also an attractive option for Linux, UNIX or Mac users wishing to set up JABAWS services quickly.</p>\r
+<h3><a name="whennotvm" id="whennotvm"/>When <em>not</em> to use the JABAWS Virtual Appliance</h3><p>\r
+For servers that will be used heavily, we recommend that a <a href="man_serverwar.html#instwar">JABAWS Server WAR distribution</a> is deployed, rather than the Virtual Appliance version of JABAWS. \r
+This is because the JABAWS appliance is pre-configured to use only 1 CPU and 512M of memory \r
+(where the minimum amount of memory required for a JABAWS server is about 378M), which is unlikely to be sufficient for heavy computation. \r
+It is possible to reconfigure the virtual appliance so it uses more computation resources, \r
+but for most production environments, the JABAWS WAR distribution will be more easy to deploy and tune to take advantage of the resources available.</p>\r
+\r
+<h3><a name="howtoinstallvm" id="howtoinstallvm"></a>How to install VMWare Player or VirtualBox</h3>\r
+<p>Please see the <a href="http://downloads.vmware.com/d/info/desktop_downloads/vmware_player/3_0">VMware Player</a>  \r
+and <a href="http://www.virtualbox.org/wiki/Download_Old_Builds_3_2">Oracle VirtualBox</a> web sites for up to date instructions and downloads.</p>\r
+\r
+<h3><a name="vmplayer" id="vmplayer"/>VMware Player appliance configuration </h3>\r
+<p>The free <a href="http://downloads.vmware.com/d/info/desktop_downloads/vmware_player/3_0">VMware Player</a> can be used to run the JABAWS services from the Windows and Linux host operating systems, there is no support for Mac at the time of writing (December 2010). \r
+However, <a href="https://www.vmware.com/vmwarestore/buyfusion.html">VMware Fusion</a>, a commercial VMware product, offers virtual machine support for Mac computers too. </p>\r
+<p>To run the JABAWS server on VMware player,  unpack the JABAWS VM into one of the folders on your local hard drive. Open VMware Player, click &quot;Open Virtual Machine&quot; and point the Player to the location of the JABAWS, then choose the JABAWS.vmx file to open an appliance. </p>\r
+<p>When you play the machine for the first time the Player might ask you whether &quot;This virtual machine may have been moved or copied.&quot;,  say that you have copied it. That is all. </p>\r
+<h3><a name="virtualbox" id="virtualbox"/></a>VirtualBox appliance configuration</h3>\r
+<p>VirtualBox can be used to run JABAWS services from Windows, Linux, Solaris or Mac host operating systems. Use the VitualBox &quot;Import  Appliance&quot; option to import the JABAWS. Please bear in mind that to benefit from multiple CPU support under the VirtualBox software you need to enable<a href="http://en.wikipedia.org/wiki/X86_virtualization"> hardware virtualization extensions</a>, such as  Intel Virtualization VT-x or AMD-V support in the BIOS of your computer. Unfortunately, we were unable to find a reliable way to do it on Mac, so some Macs running VirtualBox will be limited to one CPU only, irrespective of the number of CPUs of the host machine. </p>\r
+<p>We found that, by default, virtualization extensions are enabled in VirtualBox irrespective of whether your computer supports them. You will get the <a href="#vmbexc">VERR_VMX_MSR_LOCKED_OR_DISABLED</a> exception if your computer does not support the extensions or their support is disabled. Just deselect the checkboxes shown on the screen shot below to solve the problem. </p>\r
+<p>VirtualBox JABAWS VM configuration screen shot displaying virtualization settings.</p>\r
+<p><img src="images/vmb_virtual.png" alt="VT-x extension on VirtualBox" width="669" height="535" /></p>\r
+<h3><a name="jabawsAppliance" id="jabawsAppliance"/>JABAWS Appliance details</h3>\r
+<p>By default, the JABAWS virtual appliance is configured with 512M of memory and 1 CPU, but you are free to change these settings. If you have more than one CPU or CPU core on your computer you can make them available for the JABAWS virtual machine by editing virtual machine settings. Please bear in mind that more CPU power will not make a single calculation go faster, but it will enable the VM to do calculations in parallel. Similarly, you can add more memory to the virtual machine. More memory lets your VM deal with larger tasks, e.g. work with large alignments.</p>\r
+<p>The VMware Player screen shot below displays JABAWS VM CPU settings. </p>\r
+<p><img src="images/VMware_cpu.png" alt="vmware cpu settings" width="708" height="267" style="border: solid black 1px" /></p>\r
+\r
+<p><strong>JABAWS appliance configuration: </strong></p>\r
+<p><strong>VMware info</strong><br />\r
+  - CPUs : 1<br />\r
+  - RAM : 512 MB<br />\r
+  - Networking : Host only (the VM has no access to the outside network, nothing from the outside network can access the VM)<br />\r
+  - Hard disk : 20 GB  (expanding)<br />\r
+  - VMware tools : Installed</p>\r
+<p><strong>OS info</strong><br />\r
+  - OS : TurnKey Linux, based on Ubuntu 8.0.4 JEOS (Just-Enough-Operation-System)<br />\r
+  - Installation : Oracle Java 6, Tomcat 6, JABAWS v. 1.0 <br />\r
+  - Hostname : tomcat <br />\r
+  - IPv4 address : dhcp<br />\r
+  - IPv6 address : auto<br />\r
+  - DNS name : none<br />\r
+  - Name server : dhcp<br />\r
+  - Route : dhcp<br />\r
+  - Keyboard : US_intl</p>\r
+<p><strong>Login credentials</strong><br />\r
+  - Root password: jabaws</p>\r
+<p>  <strong>Services</strong></p>\r
+<ul>\r
+  <li>Default virtual console Alt+F7 </li>\r
+  <li>Tomcat web server. <br />\r
+    <em>Access:</em> http://VM_IP</li>\r
+  <li><strong>JABAWS URL: http://VM_IP/jabaws</strong></li>\r
+  <li>Web Shell<br />\r
+    <em>Access:</em> https://VM_IP:12320/</li>\r
+  <li>Webmean<br />\r
+    <em>Access:</em> https://VM_IP:12321/</li>\r
+  <li>SSH/SFTP<br />\r
+    <em>Access:</em> root@VM_IP</li>\r
+  </ul>\r
+<p>Where VM_IP is the VM IP address. Under VMware Player host only networking, the first VM may have 192.168.227.128 IP address. Under VirtualBox host only networking, first VM may have 192.168.56.101 IP address.</p>\r
+<h3><a name="jalviewWithJaba" id="jalviewWithJaba"/>Configuring Jalview to work with your JABAWS VM</a> </h3>\r
+<p>After booting the JABAWS VM, you should see similar screen, however, the IP address of your VM may be different. To enable Jalview to work with your JABAWS appliance you need to go to Jalview-&gt;Tools-&gt;Preferences-&gt;Web Services -&gt; New Service URL, and add JABAWS URL into the box provided. For more information please refer to Jalview <a href="http://www.jalview.org/help/html/webServices/JABAWS.html">help pages</a>. </p>\r
+<p><img src="images/vm_welcome_screen.png" alt="JABAWS welcome screen" width="734" height="461" /></p>\r
+<p>If you click on Advanced Menu, you will see the configuration console, similar to the one below.   </p>\r
+<p><img src="images/VMware_booted.png" alt="JABAWS welcome screen" width="735" height="461" /></p>\r
+<p>If you need to configure a static IP address the configuration console will help you with this. Shutting down the VM is best from the configuration console as well.</p>\r
+<h3><a name="vmiaccess" id="vmiaccess"/></a></a>VM Network Settings </h3>\r
+<p>By default the JABAWS VM is configured to use host-only networking. This means that the host can communicate with the VM via a network, but no other machines can. Similarly, the VM cannot communicate with any other computers apart from the host. If you want to connect to the Internet from the VM, configure your VM to use NAT network. However, you will not be able to connect to the VM from the host in such case. If you want to be able to connect to your VM and let VM connect to the internet at the same time you would have to use a Bridged network. In such a case you would have to configure the VM IP address manually (unless of course your network has a DHCP server to do that)</p>\r
+<h3><a name="vmbexc" id="vmbexc"/></a>VirtualBox fails to open the VM due to VERR_VMX_MSR_LOCKED_OR_DISABLED exception</h3>\r
+<p>VERR_VMX_MSR_LOCKED_OR_DISABLED exception means that Intel Virtualization technology is disabled or not supported by your computer. If you have such a problem, please make sure you have configured the JABAWS VM with 1 CPU and disabled VT-X extensions. Alternatively you can enable virtualization extensions ion from the BIOS of your computer. Unfortunately, we cannot give you  exact instructions on how to do this, as this would depend on your computer BIOS manufacturer. For MACs it may not be possible at all. </p>\r
+<h3><a name="vboxinvalidstate" id="vboxinvalidstate"></a>VirtualBox 4.0.0 fails to import the VM due to VBOX_E_INVALID_OBJECT_STATE exception </h3>\r
+<p>VirtualBox version 4.x.x is not compatible with JABAWS virtual appliance. Please download the previous version of <a href="http://www.virtualbox.org/wiki/Download_Old_Builds_3_2">VirtualBox</a> 3.2.12 to use with JABAWS VA.</p>\r
+<h3><a name="ovfOnVmware" id="ovfOnVmware"/></a>VMWare Player fails to open the VM with &quot;Fail to query source for information&quot; exception</h3>\r
+<p>At the time of writing, the latest version of VMware Player 3.1.2 supported only a legacy OVF version 0.9. Whereas OVF packaged with JABAWS VM is version 1.0. Please use VMX - VMware specific configuration file with all VMware products. </p>\r
+</div>\r
+\r
+<!-- content end-->\r
+<div id="copyright">Last update: 1 April 2011<br />\r
+ Peter Troshin, Jim Procter and Geoff Barton, The Barton Group, University of\r
+Dundee, UK</div>\r
+</div>\r
+\r
+<!-- wrapper end-->\r
+</div>\r
+<!-- page end-->\r
+\r
+<!-- Google analitics -->\r
+<script type="text/javascript">\r
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");\r
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));\r
+</script>\r
+<script type="text/javascript">\r
+try{\r
+var pageTracker = _gat._getTracker("UA-5356328-1");\r
+pageTracker._trackPageview();\r
+} catch(err) {}\r
+</script>\r
+</body>\r
+</html>\r
+\r
diff --git a/website/man_serverwar.html b/website/man_serverwar.html
new file mode 100644 (file)
index 0000000..dc994bc
--- /dev/null
@@ -0,0 +1,265 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "XHTML 1.0 Strict"\r
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<meta name="Last-modified" content="Mon, 4 Apr 2011 12:00:00 GMT"/>\r
+<title>Java Bioinformatics Analyses Web Services (JABAWS) Server Web Aplication aRchive manual</title>\r
+<link href="ws.css" rel="stylesheet" type="text/css" media=\r
+"screen, projection, handheld, tv" />\r
+<link rel="stylesheet" type="text/css" media="print" href=\r
+"print.css" />\r
+<script type="text/javascript" src="prototype-1.6.0.3.js"></script>\r
+</head>\r
+<body>\r
+<div id="page">\r
+<div id="banner">\r
+<table> \r
+<tr><td style="width:130px;"><a href="http://www.dundee.ac.uk"><img src="images/uod_lt.gif"  alt="University of Dundee" class="logo"  title="University of Dundee" longdesc="http://www.dundee.ac.uk"/></a></td>\r
+<td class="bg"><img src="images/jabaws.png" title="JABAWS:MSA" alt="JABAWS:MSA"/></td>\r
+<td class="bg"><img src="images/align.png"/></td>\r
+</tr>\r
+</table></div><!-- banner end-->\r
+\r
+<div id="wrapper">\r
+<div id="panel"><a href="index.html">Home</a> \r
+        <a href="quick_start.html">Getting Started</a> \r
+    <a class="selected" href="man_about.html">Manual</a> \r
+       <div id="submenu">\r
+               <a href="man_about.html">About</a>\r
+               <a href="man_servervm.html" title="JABAWS Server as Virtual Appliance">Server VA</a>\r
+               <a class="selected" href="man_serverwar.html" title="JABAWS Server as Web Application aRchive">Server WAR</a>\r
+               <a href="man_configuration.html" >Server<br/>\r
+               Configuration</a>\r
+               <a href="man_client.html" title="JABAWS Command Line Client">CMD Client</a>\r
+               <a href="man_dev.html" title="Accessing JABAWS from your program">Accessing<br/>\r
+               JABAWS</a>      \r
+       </div>\r
+<a href="download.html">Download</a> \r
+<a href="contacts.html">Contact Us</a>\r
+<a href="http://www.compbio.dundee.ac.uk">Barton Group</a> \r
+</div>\r
+\r
+<!-- panel end-->\r
+<div id="content">\r
+<h2 id="headtitle">JABAWS MANUAL</h2>\r
+\r
+<h2>JABAWS Server Web Application aRchive (WAR) </h2>\r
+<ul>\r
+  <li><a href="#sysreq">System Requirements</a></li>\r
+  <li><a href="#instwar">Installing the JABAWS WAR file</a></li>\r
+  <li><a href="#prepexec">Preparing executables for use with JABAWS</a></li>\r
+  <li><a href="#useprebin">Using the pre-compiled i386 binaries on Linux</a></li>\r
+  <li><a href="#recompbinaries">Recompiling the bundled\r
+    programs for your system</a></li>\r
+  <li><a href="#haveexec">Reuse the binaries that are\r
+    already in your system</a></li>\r
+  <li><a href="#obtainexec">Obtaining alignment\r
+    programs for your operating system</a></li>\r
+  <li><a href="#usingWsTester">Testing JABAWS Server</a></li>\r
+  <li><a href="#diffcontexts">Running many JABAWS instances on the same server</a> </li>\r
+  <li><a href="#nocluster">JABAWS on a single server</a></li>\r
+  <li><a href="#clustsubsys">JABAWS supported cluster batch management systems </a></li>\r
+  <li><a href="#tomstopundeploy">Manually deploying JABAWS application on Apache-Tomcat </a></li>\r
+</ul>\r
+<p><strong>Troubleshooting</strong></p>\r
+<ul>\r
+  <li><a href="#tomdeploy">Apache-Tomcat fails to deploy the jabaws.war file</a></li>\r
+  </ul>\r
+<h3><a name="sysreq" id="sysreq"></a>System Requirements</h3>\r
+<p>JABAWS requires a Java web application server compliant with\r
+version 2.4 of the Java Servlet specification, and a Java 6 runtime\r
+environment. We recommend using an official Oracle Java 6 runtime\r
+environment, and <a\r
+href="http://tomcat.apache.org/download-60.cgi">Apache-Tomcat</a> web application server version 6, but other versions may work as well.<br/><span class="attention">Please Note:</span> The JABAWS WAR is not generally compatible with older Mac systems based on the PowerPC architecture, since Java 1.6 is not available to run JABAWS.</p>\r
+\r
+<p>JABAWS Web Application aRchive can run on any host operating system that supports Java 1.6. However JABAWS depends on a number of third party programs which are not available for all operating systems. In particular, only Clustal and Muscle are currently available for MS Windows platform.\r
+  <!-- todo: link to help about obtaining and installing tomcat -->\r
+</p>\r
+<p>JABAWS comes with pre-compiled MS Windows and Linux IA32 binaries, as well as the source code and build scripts necessary to recompile them.</p>\r
+<p>To run JABAWS on the cluster you must have shared disk space accessible from all cluster nodes. </p>\r
+<h3><a name="instwar" id="instwar"></a>Installing the JABAWS WAR file</h3>\r
+<p>JABAWS is distributed as a web application archive (WAR). To\r
+deploy JABAWS in Apache-Tomcat - simply drop the war file into the\r
+<span class="highlight">webapps</span> directory of a running\r
+Tomcat, and it will do the rest. If you used this deployment procedure, <span class="attention">do not remove</span> the jabaws WAR file, otherwise Tomcat will undeploy your application! The context path for your deployed application will be the same as the name of the war file. For example, assuming the Tomcat server is running on the <span class="hightlight">localhost:8080</span> and <strong>jaba.war</strong> file is put into the <span class="hightlight">&lt;tomcat server root&gt;/webapps</span> directory, the deployed application from the jaba.war file then can be accessed by this URL http://localhost:8080/<strong>jaba</strong>. </p>\r
+<p>For any other web application\r
+  server, please follow your server's specific deployment procedure\r
+  for 'WAR' files. If you install JABAWS on a MS Windows machine, then\r
+  at this point your JABAWS installation will already be up and\r
+  running, and you can try its services out <a href=\r
+"#usingWsTester">as described here</a>. If you install JABAWS on Linux you will need to set an executable flag for binaries. This is described  <a href="#useprebin">here</a>. If your host operating system is different from Windows or Linux then read on. </p>\r
+<h3><a name="prepexec" id="prepexec"></a>Preparing executables for use with JABAWS</h3>\r
+\r
+<p>JABAWS's web services use command line programs to do\r
+the actual analysis, so it must have access to programs\r
+which can be executed on your platform. The native executables\r
+bundled with JABAWS for Windows (32-bit) and Linux (i386, 32-bit) should be\r
+OK for those systems. The source code for these \r
+programs is also provided so you can <a href="#recompbinaries">recompile for your own\r
+architecture</a> and exploit any optimizations that your system can\r
+provide. Alternately, if you have already got binaries on your\r
+system, then you can simply <a href="#haveexec">change the paths in JABAWS's\r
+configuration files</a> so these are used instead.</p>\r
+\r
+<h3><a name="useprebin" id="useprebin"></a>Using the pre-compiled i386 binaries on Linux</h3>\r
+\r
+<p>Before the binaries that are bundled with JABAWS can be used,\r
+they must first be made executable using the provided <a name=\r
+"setexecflag" id="setexecflag">'setexecflag.sh'</a> script:</p>\r
+\r
+<ol>\r
+<li>cd to <span class=\r
+"hightlight">&lt;webapplicationpath&gt;/binaries/src</span></li>\r
+\r
+<li>run <span class="hightlight">sh setexecflag.sh</span></li>\r
+\r
+<li>Make sure binaries supplied work under your OS.<br />\r
+ For this run each binary, without any command line options or\r
+input files. If you see an error message complaining about missing\r
+libraries or other problems, then you probably need to <a href=\r
+"#recompbinaries">recompile the binaries</a>.</li>\r
+\r
+<li>Restart the Tomcat.</li>\r
+</ol>\r
+\r
+That's it! JABAWS should work at this point. Try it out using the JABAWS<a\r
+href="#usingWsTester"> test client</a>. If not,\r
+read on... or have a look at <a href="http://tomcat.apache.org/tomcat-6.0-doc/deployer-howto.html">deploying on Tomcat</a> tips.<br />\r
+ <em>Note: You may want to enable logging, <a href="man_configuration.html#logfiles"> as described here</a></em>.<br />\r
\r
+\r
+<h3><a name="recompbinaries">Recompiling the bundled\r
+programs for your system</a></h3>\r
+\r
+<p>If you have a fully equipped build environment on your\r
+(POSIX-like) system, then you should be able to recompile the\r
+programs from the source distributions which are included\r
+in the JABAWS war file. A script called 'compilebin.sh' is provided\r
+to automate this task.</p>\r
+\r
+<ol>\r
+<li>In a terminal window, change the working directory to <span\r
+class="hightlight">binaries/src</span></li>\r
+\r
+<li>execute the <span class="highlight">compilebin.sh</span>\r
+script,<br />\r
+ either use: <span class="hightlight">chmod +x compilebin.sh;\r
+compilebin.sh &gt; compilebin.out;</span><br />\r
+ or: <span class="hightlight">sh compilebin.sh &gt;\r
+compilebin.out</span></li>\r
+\r
+<li>Now run <span class="hightlight">sh setexecflag.sh</span><br />\r
+ If any of the binaries was not recompiled, then a 'file not found'\r
+error will be raised.</li>\r
+\r
+<li>Finally, restart your Tomcat server (or JABAWS application only), and <a href="#usingWsTester">test JABAWS</a> to\r
+check that it can use the new binaries.</li>\r
+</ol>\r
+\r
+<p>If you couldn't compile everything, then it may be that your system does\r
+not have all the tools required for compiling the programs. At the very\r
+least check that you have gcc, g++ and make installed in your\r
+system. If not install these packages and repeat the compilation\r
+steps again. You should also review the compilebin.sh output -\r
+which was redirected to compilebin.out, and any errors output to\r
+the terminal. Finally, try obtaining the <a href="#obtainexec">pre\r
+compiled binaries</a> for your OS.</p>\r
+\r
+<h3><a name="haveexec" id="haveexec">Reuse the binaries that are\r
+already in your system</a></h3>\r
+\r
+<p>If you would like to use the binaries you already have then you\r
+just need to let JABAWS know there they are. To do this, edit:\r
+<span class="code">conf/Executable.properties</span></p>\r
+<p>When specifying paths to executables that already exist on your system, make sure you provide an absolute path, or one relative to the JABAWS directory inside <span class="highlight">webapps</span>. For example, the default path for clustalw is defined\r
+as<span class=\r
+"code">local.clustalw.bin=binaries/src/clustalw/src/clustalw2</span>\r
+Alternatively, instead of changing <span class=\r
+"hightlight">Executable.properties</span> you could also replace\r
+the executables bundled with JABAWS with the ones that you have, or make symbolic links to them.\r
+Then the default configuration will work for you. More information\r
+about <span class="hightlight">the\r
+Executable.properties</span> file is given in the <a href="man_configuration.html#exec">JABAWS Configuration chapter.</a></p>\r
+\r
+<h3><a name="obtainexec" id="obtainexec">Obtaining alignment\r
+programs for your operating system</a></h3>\r
+\r
+<p>You could search for pre-packaged compiled executable in your\r
+system package repository or alternately, download pre-compiled\r
+binaries from each alignment program's home page. Then, either\r
+replace the executables supplied with the downloaded ones, or\r
+modify the paths in <span class=\r
+"hightlight">executable.properties</span> as described above. Below are some suggestions on where you may be able to get the binaries for your system. </p>\r
+<ul>\r
+  <li><a href="ftp://ftp.ebi.ac.uk/pub/software/clustalw2/2.0.12/">ClustalW</a></li>\r
+  <li><a href="http://mafft.cbrc.jp/alignment/software/">Mafft</a></li>\r
+  <li><a href="http://www.drive5.com/muscle/download3.6.html">Muscle</a></li>\r
+  <li><a href="http://www.tcoffee.org/Packages/Binaries/">Tcoffee</a></li>\r
+  <li>Probcons (Linux <a href="http://www.compbio.dundee.ac.uk/jabaws/archive/binaries/linuxI386/probcons/">I386</a> | <a href="http://www.compbio.dundee.ac.uk/jabaws/archive/binaries/linuxAMD64/probcons/">AMD64</a>)</li>\r
+</ul>\r
+<h3><a name="usingWsTester" id="usingWsTester"></a>Testing JABAWS Server </h3>\r
+<p>First of all make sure that Tomcat server is started successfully. If this was the case, then you should see JABAWS home page when you navigate to your Tomcat JABAWS context path e.g. <span class="code">http://myhost.compbio.ac.uk:8080/jabaws</span>If you see it, then it is time to make sure that web services are working too. Assuming that you have unpacked/deployed JABAWS from the server war file, you should be able to navigate to the test program which can be found in &lt;webapplicationpath&gt;/WEB-INF/lib/jabaws-client.jar file. To run the tests type:<span class="code"> java -jar jabaws-client.jar -h=&lt;Your web application server host name, port and JABAWS context path&gt;</span></p>\r
+<p>For example to test all JABAWS web services on host myhost.compbio.ac.uk type: </p>\r
+<p class="code">java -jar jabaws-client.jar -h=http://myhost.compbio.ac.uk:8080/jabaws </p>\r
+<p>You can choose a particular web server using -s option like this <span class="code">java -jar jabaws-client.jar -h=http://myhost.compbio.ac.uk:8080/jabaws -s=ClustalWS </span>This command line assumes that java executable is in your path and jabaws-client.jar is located in the current directory.</p>\r
+<p>An example of the report testing tool produces for operating web service looks like this: </p>\r
+<p><span class="code"> Connecting to service MuscleWS on http://myhost.compbio.ac.uk:8080/jabaws ... OK<br />\r
+  Testing alignment with default parameters:<br />\r
+  Queering job status...OK<br />\r
+  Retrieving results...OK<br />\r
+  Testing alignment with presets:<br />\r
+  Aligning with preset 'Protein alignment(Fastest speed)'... OK<br />\r
+  Aligning with preset 'Nucleotide alignment(Fastest speed)'... OK<br />\r
+  Aligning with preset 'Huge alignments (speed-oriented)'... OK<br />\r
+  Queering presets...OK<br />\r
+  Queering Parameters...OK<br />\r
+  Queering Limits...OK<br />\r
+  Queering Local Engine Limits...OK<br />\r
+  Check is completed service MuscleWS IS WORKING</span>An example of the response of a web service which is deployed but is not operating is below: </p>\r
+<p><span class="code">Connecting to service ProbconsWS on http://localhost:8080/ws ... OK<br />\r
+  Testing alignment with default parameters:FAILED<br />\r
+  Service ProbconsWS IS NOT FUNCTIONAL</span>If the web server did not respond the message looks like following: <span class="code">Connecting to service TcoffeeWS on http://localhost:8080/ws ... FAILED</span></p>\r
+<h3><a name="diffcontexts" id="diffcontexts"/></a></a>Running many JABAWS instances on the same server</h3>\r
+<p> JABAWS is supplied as a Web Application aRchive which can be dealt with as any other web applications. So it is perfectly possible to run two JABAWS instances from the same server. Just make two different contexts on your application server and unpack JABAWS in both of them. For example if your server name is http://www.align.ac.uk, and the context names are public and private. Than one group of users could be given a URL http://www.align.ac.uk/public and another http://www.align.ac.uk/private. These contexts will be served by two independent JABAWS instances, and could be configured differently. If you keep local engine enabled, make sure you reduce the number of threads local engine is allowed to use to avoid overloading the server. Alternatively two completely separate web application server instances (e.g. Apache-Tomcat) could be used. This will give you a better resilience and more flexibility in memory settings. </p>\r
+<h3><a name="nocluster" id="nocluster"></a>JABAWS on a single server</h3>\r
+<p>You can run  JABAWS on a single server. Obviously the capacity will be limited, but may be sufficient for a small lab. Installed on a single server, JABAWS executes tasks in parallel, so the more cores the server has the more requests it will be able to handle. </p>\r
+<h3><a name="clustsubsys" id="clustsubsys"></a>JABAWS supported cluster batch management systems </h3>\r
+<p>JABAWS uses <a href="http://drmaa.org/">DRMAA</a> v. 1.0 library to send and manage jobs on the cluster. DRMAA supports many different cluster job management systems. Namely Sun Grid Engine, Condor, PBS, GridWay, Globus 2/4, PBSPro, LSF. For up to date information please consult DRMAA web site. We found that DRMAA implementation differ from platform to platform and were trying to use only the basic functions. We have only tested JABAWS on Sun Grid Engine v 6.2. Please let use know if you have any experience of running JABAWS on other platforms.</p>\r
+<h3><a name="tomstopundeploy" id="tomstopundeploy"></a>Manually deploying JABAWS application on Apache-Tomcat </h3>\r
+<p>To stop Tomcat from automatically undeploying your application if the war file is removed use an explicit application descriptor. It could come in different flavors, the one I prefer if to drop a context descriptor file into <span class="hightlight">&lt;tomcatRoot&gt;conf/Catalina/localhost</span> directory. Name your context file the same as your application folder e.g. if you JABAWS resides in webappl/jabaws folder, then call the context file jabaws.xml. Below is an example of content this file might have.</p>\r
+<p class="code">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;<br />\r
+  &lt;Context antiResourceLocking=&quot;false&quot; privileged=&quot;true&quot;  /&gt;</p>\r
+<p>This should be sufficient to prevent Tomcat from removing your JABAWS from WEBAPPS. For more information about the Tomcat deployer <a href="http://tomcat.apache.org/tomcat-6.0-doc/deployer-howto.html">read this documentation on the Apache-Tomcat web site</a>.</p>\r
+<h3><a name="tomdeploy" id="tomdeploy"></a>Apache-Tomcat fails to deploy jabaws.war file </h3>\r
+<ul>\r
+  <li>Make sure Tomcat have sufficient access rights to read your war file. </li>\r
+  <li>Restart the Tomcat, sometimes it will not since that the new war file is added without restart</li>\r
+  <li>If Tomcat still refuses to unpack the war file, unpack it manually into web application folder (the war file is just a zip archive). Restart the Tomcat.</li>\r
+</ul>\r
+</div>\r
+\r
+<!-- content end-->\r
+<div id="copyright">Last update: 1 April 2011<br />\r
+ Peter Troshin, Jim Procter and Geoff Barton, The Barton Group, University of\r
+Dundee, UK</div>\r
+</div>\r
+\r
+<!-- wrapper end-->\r
+</div>\r
+<!-- page end-->\r
+\r
+<!-- Google analitics -->\r
+<script type="text/javascript">\r
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");\r
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));\r
+</script>\r
+<script type="text/javascript">\r
+try{\r
+var pageTracker = _gat._getTracker("UA-5356328-1");\r
+pageTracker._trackPageview();\r
+} catch(err) {}\r
+</script>\r
+</body>\r
+</html>\r
+\r
diff --git a/website/manual_qs_client.html b/website/manual_qs_client.html
new file mode 100644 (file)
index 0000000..a8b6599
--- /dev/null
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "XHTML 1.0 Strict" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<meta name="Last-modified" content="Mon, 4 Apr 2011 12:00:00 GMT"/>\r
+<title>Java Bioinformatics Analyses Web Services (JABAWS) manual - getting started</title>\r
+<link href="ws.css" rel="stylesheet" type="text/css" media="screen,  projection, handheld, tv" />\r
+<link rel="stylesheet" type="text/css" media="print" href="print.css"/>\r
+\r
+<script type="text/javascript" src="prototype-1.6.0.3.js"></script>\r
+</head>\r
+<body>\r
+<div id="page">\r
+<div id="banner"><table> \r
+<tr><td style="width:130px;"><a href="http://www.dundee.ac.uk"><img src="images/uod_lt.gif"  alt="University of Dundee" class="logo"  title="University of Dundee" longdesc="http://www.dundee.ac.uk"/></a></td>\r
+<td class="bg"><img src="images/jabaws.png" title="JABAWS:MSA" alt="JABAWS:MSA"/></td>\r
+<td class="bg"><img src="images/align.png"/></td>\r
+</tr>\r
+</table>\r
+</div><!-- banner end-->\r
+<div id="wrapper">\r
+<div id="panel">\r
+<a href="index.html">Home</a>\r
+    <a class="selected" href="quick_start.html">Getting Started</a> \r
+    <a href="man_about.html">Manual</a> \r
+       <a href="download.html">Download</a>\r
+       <a href="contacts.html">Contact Us</a>\r
+       <a href="http://www.compbio.dundee.ac.uk">Barton Group</a></div>\r
+<!-- panel end-->      \r
+\r
+<div id="content">\r
+\r
+<h2 id="headtitle">Getting Started</h2>\r
+\r
+<h3><a name="whichjaba" id="whichjaba"></a>Choose a JABAWS distribution</h3>\r
+\r
+<table id="choicematrix">\r
+<tr>\r
+  <th>I want to use JABAWS for...</th>\r
+  <th>Quick Guide</th>\r
+</tr>\r
+<tr>\r
+       <td>Running Muptiple Sequence Alignments through Jalview on my <strong>own</strong> computer</td>\r
+    <td><a href="manual_qs_va.html#qsc">JABAWS Virtual Appliance (VA)</a></td>\r
+</tr>\r
+<tr>\r
+       <td>Running JABAWS for my group, lab, or organization</td>\r
+    <td><a href="manual_qs_war.html#qsc">JABAWS Web Application aRchive (WAR)</a></td>\r
+</tr>\r
+<tr>\r
+       <td>Accessing a JABAWS server from my own code</td>\r
+    <td><a href="manual_qs_client.html#qsc">JABAWS Java Client</a></td>\r
+</tr>\r
+</table>\r
+\r
+\r
+\r
+\r
+<a name="qsc"/>\r
+<h3><a name="client"/>The JABAWS command line client</h3>\r
+<ul><li><a href=\r
+"http://www.compbio.dundee.ac.uk/jabaws/archive/min-jaba-client.jar">Download the Client Jar</a> (80 K)</li>\r
+</ul>\r
+</p>\r
+<p>This is a single java archive which contains the JABAWS command line client. \r
+It requires Java version 1.6 to run, and allows anyone who wants to connect \r
+to and to use JABAWS from their own software. \r
+You can read more about how to use command line client <a href="man_client.html">in the CMD Client</a> section of the manual. \r
+You can also get command line help by changing to the directory where you downloaded the client jar, and typing:\r
+<ul>\r
+       <li><span class="hightlight">java -jar min-jaba-client.jar</span></li>\r
+</ul></p>\r
+<p>A JABAWS server's Web Services are WS-I compliant. This means that you can access them from any \r
+language that has libraries or functions for consuming interoperable SOAP web services.\r
+<!-- PETER TODO Provide list of libraries for different languages --></p>\r
+</div> \r
+<!-- about end-->\r
+</div>\r
+<!-- content end--> \r
+<div id="copyright">Last update: 1 April 2011<br/>\r
+Peter Troshin, Jim Procter and Geoff Barton, The Barton Group, University of Dundee, UK</div>\r
+</div><!-- wrapper end-->\r
+</div> <!-- page end-->\r
+\r
+<!-- Google analitics -->\r
+<script type="text/javascript">\r
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");\r
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));\r
+</script>\r
+<script type="text/javascript">\r
+try{\r
+var pageTracker = _gat._getTracker("UA-5356328-1");\r
+pageTracker._trackPageview();\r
+} catch(err) {}\r
+</script>\r
+</body>\r
+</html>\r
+\r
diff --git a/website/manual_qs_va.html b/website/manual_qs_va.html
new file mode 100644 (file)
index 0000000..e0c928e
--- /dev/null
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "XHTML 1.0 Strict" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<meta name="Last-modified" content="Mon, 4 Apr 2011 12:00:00 GMT"/>\r
+<title>Java Bioinformatics Analyses Web Services (JABAWS) manual - getting started</title>\r
+<link href="ws.css" rel="stylesheet" type="text/css" media="screen,  projection, handheld, tv" />\r
+<link rel="stylesheet" type="text/css" media="print" href="print.css"/>\r
+\r
+<script type="text/javascript" src="prototype-1.6.0.3.js"></script>\r
+</head>\r
+<body>\r
+<div id="page">\r
+<div id="banner"><table> \r
+<tr><td style="width:130px;"><a href="http://www.dundee.ac.uk"><img src="images/uod_lt.gif"  alt="University of Dundee" class="logo"  title="University of Dundee" longdesc="http://www.dundee.ac.uk"/></a></td>\r
+<td class="bg"><img src="images/jabaws.png" title="JABAWS:MSA" alt="JABAWS:MSA"/></td>\r
+<td class="bg"><img src="images/align.png"/></td>\r
+</tr>\r
+</table>\r
+</div><!-- banner end-->\r
+<div id="wrapper">\r
+<div id="panel">\r
+<a href="index.html">Home</a>\r
+    <a class="selected" href="quick_start.html">Getting Started</a> \r
+    <a href="man_about.html">Manual</a> \r
+       <a href="download.html">Download</a>\r
+       <a href="contacts.html">Contact Us</a>\r
+       <a href="http://www.compbio.dundee.ac.uk">Barton Group</a></div>\r
+<!-- panel end-->\r
+<div id="content">\r
+\r
+<h2 id="headtitle">Getting Started</h2>\r
+\r
+<h3><a name="whichjaba" id="whichjaba"></a>Choose a JABAWS distribution</h3>\r
+\r
+<table id="choicematrix">\r
+<tr>\r
+  <th>I want to use JABAWS for...</th>\r
+  <th>Quick Guide</th>\r
+</tr>\r
+<tr>\r
+       <td>Running Muptiple Sequence Alignments through Jalview on my <strong>own</strong> computer</td>\r
+    <td><a href="manual_qs_va.html#qsc">JABAWS Virtual Appliance (VA)</a></td>\r
+</tr>\r
+<tr>\r
+       <td>Running JABAWS for my group, lab, or organization</td>\r
+    <td><a href="manual_qs_war.html#qsc">JABAWS Web Application aRchive (WAR)</a></td>\r
+</tr>\r
+<tr>\r
+       <td>Accessing a JABAWS server from my own code</td>\r
+    <td><a href="manual_qs_client.html#qsc">JABAWS Java Client</a></td>\r
+</tr>\r
+</table>\r
+\r
+<a name="qsc"/>\r
+<h3>Running JABAWS on your local machine</h3>\r
+<ul>  <li>Download <a href="http://www.compbio.dundee.ac.uk/jabaws/archive/jabaws-vm.zip">JABAWS Virtual Appliance</a> (520M) </li>\r
+</ul>\r
+<p>The Virtual Appliance (VA) package allows you to run a JABAWS server installed on TurnKey Linux as a virtual machine on your laptop or desktop computer. A <a href="man_servervm.html#whenvm">complete guide to the JABAWS VA</a> is given in the manual, but for the impatient, a brief instructions are given below:\r
+\r
+<p>If you work on Windows, Linux or Unix </p>\r
+<ol>\r
+  <li>download and install <a href="http://www.vmware.com/products/player">VMWare Player</a>.</li>\r
+  <li>Unpack the JABAWS virtual appliance and open it with VMware Player.</li>\r
+  </ol>\r
+<p>If you use a Mac, or prefer not to use VMWare, then :</p>\r
+<ol>\r
+  <li>download and install <a href="http://www.virtualbox.org/wiki/Download_Old_Builds_3_2">Virtual Box</a>.</li>\r
+  <li>Unpack the JABAWS virtual appliance, import it into VirtualBox and then start the appliance. </li>\r
+</ol>\r
+<div id="testing_jabaws">\r
+<h3>Testing</h3>\r
+<p>The easiest way to test that your JABAWS Virtual appliance is working is to use Jalview.</p>\r
+<ol>\r
+  <li>Launch the desktop version of <a href="http://www.jalview.org/download.html">Jalview</a></li>\r
+  <li>Open the Jalview desktop's preferences panel (from the Tools-&gt;Preferences menu option), select the <span class="hightlight">Webservices</span> panel and press the <span class="hightlight">New Service URL</span> button.</li>\r
+  <li>Enter the JABAWS URL for your new server. This is shown once the appliance is booted up.</li>\r
+</ol>\r
+</div> \r
+</div>\r
+<!-- about end-->\r
+</div>\r
+<!-- content end--> \r
+<div id="copyright">Last update: 1 April 2011<br/>\r
+Peter Troshin, Jim Procter and Geoff Barton, The Barton Group, University of Dundee, UK</div>\r
+</div><!-- wrapper end-->\r
+</div> <!-- page end-->\r
+\r
+<!-- Google analitics -->\r
+<script type="text/javascript">\r
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");\r
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));\r
+</script>\r
+<script type="text/javascript">\r
+try{\r
+var pageTracker = _gat._getTracker("UA-5356328-1");\r
+pageTracker._trackPageview();\r
+} catch(err) {}\r
+</script>\r
+</body>\r
+</html>\r
+\r
diff --git a/website/manual_qs_war.html b/website/manual_qs_war.html
new file mode 100644 (file)
index 0000000..0887429
--- /dev/null
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "XHTML 1.0 Strict" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<meta name="Last-modified" content="Mon, 4 Apr 2011 12:00:00 GMT"/>\r
+<title>Java Bioinformatics Analyses Web Services (JABAWS) manual - getting started</title>\r
+<link href="ws.css" rel="stylesheet" type="text/css" media="screen,  projection, handheld, tv" />\r
+<link rel="stylesheet" type="text/css" media="print" href="print.css"/>\r
+\r
+<script type="text/javascript" src="prototype-1.6.0.3.js"></script>\r
+</head>\r
+<body>\r
+<div id="page">\r
+<div id="banner"><table> \r
+<tr><td style="width:130px;"><a href="http://www.dundee.ac.uk"><img src="images/uod_lt.gif"  alt="University of Dundee" class="logo"  title="University of Dundee" longdesc="http://www.dundee.ac.uk"/></a></td>\r
+<td class="bg"><img src="images/jabaws.png" title="JABAWS:MSA" alt="JABAWS:MSA"/></td>\r
+<td class="bg"><img src="images/align.png"/></td>\r
+</tr>\r
+</table>\r
+</div><!-- banner end-->\r
+\r
+<div id="wrapper">\r
+<div id="panel">\r
+<a href="index.html">Home</a>\r
+    <a class="selected" href="quick_start.html">Getting Started</a> \r
+    <a href="man_about.html">Manual</a> \r
+       <a href="download.html">Download</a>\r
+       <a href="contacts.html">Contact Us</a>\r
+       <a href="http://www.compbio.dundee.ac.uk">Barton Group</a>\r
+</div><!-- panel end-->\r
+\r
+<div id="content">\r
+\r
+<h2 id="headtitle">Getting Started</h2>\r
+\r
+<h3><a name="whichjaba" id="whichjaba"></a>Choose a JABAWS distribution</h3>\r
+\r
+<table id="choicematrix">\r
+<tr>\r
+  <th>I want to use JABAWS for...</th>\r
+  <th>Quick Guide</th>\r
+</tr>\r
+<tr>\r
+       <td>Running Muptiple Sequence Alignments through Jalview on my <strong>own</strong> computer</td>\r
+    <td><a href="manual_qs_va.html#qsc">JABAWS Virtual Appliance (VA)</a></td>\r
+</tr>\r
+<tr>\r
+       <td>Running JABAWS for my group, lab, or organization</td>\r
+    <td><a href="manual_qs_war.html#qsc">JABAWS Web Application aRchive (WAR)</a></td>\r
+</tr>\r
+<tr>\r
+       <td>Accessing a JABAWS server from my own code</td>\r
+    <td><a href="manual_qs_client.html#qsc">JABAWS Java Client</a></td>\r
+</tr>\r
+</table>\r
+\r
+<a name="qsc"/>\r
+\r
+<h3>Installing A JABAWS Server Web Application Archive (WAR) package</h3>\r
+\r
+<p>This is for anyone who wants to run JABAWS for their group, lab or organization, or wants to enable their local JABA server to use the cluster or perform very large tasks.</p>\r
+\r
+<ol>\r
+<li>Download the <a href="http://www.compbio.dundee.ac.uk/jabaws/archive/jaba.war">JABAWS WAR with all binaries</a> (45M)</li>\r
+  <li>Download and install <a href="http://tomcat.apache.org/download-60.cgi">Apache-Tomcat</a>.<br/>\r
+   <span class="hightlight">You will need at least version 5.5 of Tomcat (we would recommend version 6.0) and at least version 1.6 (i.e. JAVA 6) of Java.</span></li>\r
+  <li>Drop the JABAWS WAR file into <span class="hightlight">tomcat/webapps</span> directory.</li>\r
+  <li>(Re)start the Tomcat.</li>\r
+  <li>Once the tomcat has started, it should automatically unpack the WAR into the webapps directory (if it doesn't, then you'll need to do this manually, it's just a zip archive in the end).</li>\r
+  <li>You then need to complete the installation of the executable binaries:</li>\r
+   <ul><li>If you are on Linux<br/><span class="hightlight">cd</span> to <span class="hightlight"> webapps/jabaws/binaries/src/</span> and execute <span class="hightlight">./setexecflag.sh </span> script to ensure the JABAWS binaries can be executed. </li>\r
+       <li>If you are on a Mac (OSX intel mac only) or other unix-like architecture with gnu compilers available:</li>\r
+       <li> <span class="hightlight">cd</span> to <span class="hightlight">webapps/jabaws/binaries/src/</span> and execute <span class="hightlight">./compilebin.sh  </span> script to compile all binaries JABAWS depends on. </li>\r
+  <li><span class="hightlight">cd</span> to <span class="hightlight"> webapps/jabaws/binaries/src/ </span>and execute <span class="hightlight">./setexecflag.sh </span> script. </li>\r
+  </ul>\r
+</ol> \r
+\r
+<h3>Testing</h3>\r
+<p>You can test that your JABAWS server is working in two ways.</p>\r
+<ol>\r
+<li>If you are working on the command line, then use the command line client shipped with the JABAWS war to test it by running:\r
+<span class="code">java -jar &lt;Path to tomcat WebApp directory&gt;/jabaws/WEB-INF/lib/jaba-client.jar -h http://localhost:8080/jabaws</span>\r
+In this example we assumed that your JABAWS server URL is <span class="hightlight">http://localhost:8080</span> and JABAWS context path is <span class="hightlight">jabaws</span>\r
+</li>\r
+\r
+<li>Alternately, you can point Jalview at your new server:\r
+<ul>\r
+  <li>Launch the desktop version of <a href="http://www.jalview.org/download.html">Jalview</a></li>\r
+  <li>Open the Jalview desktop's preferences panel (from the Tools-&gt;Preferences menu option), select the <span class="hightlight">Webservices</span> panel and press the <span class="hightlight">New Service URL</span> button.</li>\r
+  <li>Enter the URL for the tomcat server, including the context path for the JABAWS web app (e.g. http://localhost:8080/jabaws).</li>\r
+</ul>\r
+</li></ol>\r
+\r
+<!--  TODO put JABAWS CMD test instructions here -->\r
+</div> <!-- content end-->\r
+<!-- about end-->\r
+<div id="copyright">Last update: 1 April 2011<br/>\r
+Peter Troshin, Jim Procter and Geoff Barton, The Barton Group, University of Dundee, UK</div>\r
+\r
+</div><!-- wrapper end -->\r
+\r
+<!-- Google analitics -->\r
+<script type="text/javascript">\r
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");\r
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));\r
+</script>\r
+<script type="text/javascript">\r
+try{\r
+var pageTracker = _gat._getTracker("UA-5356328-1");\r
+pageTracker._trackPageview();\r
+} catch(err) {}\r
+</script>\r
+</div> <!-- page end -->\r
+</body>\r
+</html>\r
+\r
diff --git a/website/print.css b/website/print.css
new file mode 100644 (file)
index 0000000..4f6e7b8
--- /dev/null
@@ -0,0 +1,188 @@
+\r
+#banner { background:none !important; color:#000000 !important; text-align:center; }\r
+\r
+#panel { display:none !important }\r
+\r
+#content { margin:0.5em; border-bottom:solid 1px #6994af; }\r
+\r
+#page { margin: 0.5em; }\r
+\r
+#wrapper { background:none; }\r
+\r
+ul {\r
+       list-style-type: circle;\r
+}\r
+\r
+\r
+#panel a:link, a:visited {\r
+           text-decoration: none;\r
+               display:block;\r
+               line-height: 1em;\r
+               padding:10px;\r
+               color:#000000; \r
+               text-decoration:none;\r
+        }\r
+        \r
+#panel a:hover {\r
+           background-color: transparent;\r
+           text-decoration: underline;\r
+       }\r
+\r
+\r
+strong {\r
+       font-weight:bold;\r
+       color:#003366;\r
+}\r
+\r
+pre {\r
+       font-family:Arial, Helvetica, sans-serif;\r
+}\r
+\r
+p { \r
+       line-height: 1.4em;\r
+}\r
\r
+.hightlight { \r
+font-style:italic;\r
+font-family:"Courier New", Courier, monospace;\r
+}\r
+\r
+.code { \r
+       font-size-adjust:0.4;\r
+       color:black;\r
+       background-color:#F5F5F5;\r
+       font-family:"Courier New",Courier,monospace;\r
+       font-style:normal;\r
+       margin:1em 0;\r
+       padding: 0.5em;\r
+       border: 1px dashed black;\r
+}\r
+\r
+\r
+.box { \r
+       font-size-adjust:0.5;\r
+       color:black;\r
+       background-color:#F5F5F5;\r
+       font-family:Arial, Helvetica, sans-serif;\r
+       font-style:normal;\r
+       margin:1em 0;\r
+       padding: 0.5em;\r
+       border: 1px solid black;\r
+       display:block;\r
+}\r
+\r
+.u { text-decoration: underline; }\r
+.headeru { text-shadow: black 0.05em 0.05em 0.01em ;} \r
+\r
+/* Table styles */\r
+table {\r
+       border-collapse: collapse; \r
+       border: 1px solid #666;\r
+       margin: 20px 0 20px 0;\r
+       width: 100%;\r
+}\r
+th, td {\r
+       margin: 2px 4px 2px 4px;\r
+       padding: 0 5px;\r
+       text-align: left;\r
+       vertical-align: top;\r
+       border: 1px solid #666;\r
+}\r
+\r
+table caption {\r
+       font: 1.5em Georgia, "Times New Roman", Times, serif; \r
+       padding: 1em;\r
+       background-color: #9c9;\r
+}\r
+\r
+.mainheader {\r
+       font: 1.5em Georgia, "Times New Roman", Times, serif; \r
+       background-color: #9c9;\r
+       text-align:center;\r
+       line-height:1em;\r
+}\r
+\r
+tr {\r
+        background-color: #eee; \r
+}\r
+\r
+tr:nth-child(odd) {\r
+        background-color: #ccc; \r
+}\r
+\r
+\r
+span.directory {\r
+background: transparent url(images/dir.gif) no-repeat scroll left center;\r
+color:#666666;\r
+font-family:"Courier New",Courier,monospace;\r
+font-style:normal;\r
+padding:0 0 0 15px;\r
+}\r
+\r
+.attention { \r
+color:#993333;\r
+}\r
+\r
+.source { \r
+       border:1px solid #858789;\r
+       display:block;\r
+       margin:26px 0;\r
+       overflow:visible;\r
+}\r
+\r
+/* OPEN state styles */\r
+.source .body {\r
+       background:#F5F5F5 none repeat scroll right 0;\r
+       color:#434546;\r
+       padding:7px 15px;\r
+/*     white-space:pre-wrap; */\r
+       word-wrap:break-word;\r
+}\r
+\r
+.source .header {\r
+       background:#E9EAEC url(images/minus.png) no-repeat scroll 98% center;\r
+       color:#3B3D3F;\r
+       cursor:pointer;\r
+       font-weight:bold;\r
+       height:30px;\r
+       line-height:30px;\r
+       padding:0 0 0 15px;\r
+}\r
+\r
+/* CLOSED state styles */\r
+.source .body.collapsed {\r
+       display:block !important;\r
+}\r
+\r
+.source .header.collapsed  {\r
+       background:#E9EAEC url(images/plus.png) no-repeat scroll 98% center;\r
+       padding:0 15px 0 15px;\r
+}\r
+\r
+#copyright { text-align:right; \r
+                        color:#999999; \r
+                        font-family:Verdana, Arial, Helvetica, sans-serif;\r
+                        font-size:smaller;\r
+                        line-height:1em;\r
+ }\r
+\r
+.body .code { \r
+       margin:0;\r
+       padding:0;\r
+       border:0;\r
+       font-family:"Courier New",Courier,monospace;\r
+       font-style:normal;\r
+}\r
+\r
+body {\r
+       font-family:Arial, Helvetica, sans-serif;\r
+       font-size: 9pt;\r
+       background-color: white;\r
+       line-height: 2em;\r
+}\r
+\r
+h3 {border-bottom: 1px solid grey; margin-top: 2em; }\r
+\r
+#headtitle { margin:0; text-align:center; color:#003b62; font-weight:600;} \r
+\r
+h2 {margin:1.8em 0 0 0; color:#003b62; font-weight:600;}\r
diff --git a/website/prototype-1.6.0.3.js b/website/prototype-1.6.0.3.js
new file mode 100644 (file)
index 0000000..dfe8ab4
--- /dev/null
@@ -0,0 +1,4320 @@
+/*  Prototype JavaScript framework, version 1.6.0.3
+ *  (c) 2005-2008 Sam Stephenson
+ *
+ *  Prototype is freely distributable under the terms of an MIT-style license.
+ *  For details, see the Prototype web site: http://www.prototypejs.org/
+ *
+ *--------------------------------------------------------------------------*/
+
+var Prototype = {
+  Version: '1.6.0.3',
+
+  Browser: {
+    IE:     !!(window.attachEvent &&
+      navigator.userAgent.indexOf('Opera') === -1),
+    Opera:  navigator.userAgent.indexOf('Opera') > -1,
+    WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+    Gecko:  navigator.userAgent.indexOf('Gecko') > -1 &&
+      navigator.userAgent.indexOf('KHTML') === -1,
+    MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+  },
+
+  BrowserFeatures: {
+    XPath: !!document.evaluate,
+    SelectorsAPI: !!document.querySelector,
+    ElementExtensions: !!window.HTMLElement,
+    SpecificElementExtensions:
+      document.createElement('div')['__proto__'] &&
+      document.createElement('div')['__proto__'] !==
+        document.createElement('form')['__proto__']
+  },
+
+  ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+  JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+  emptyFunction: function() { },
+  K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+  Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+
+/* Based on Alex Arnell's inheritance implementation. */
+var Class = {
+  create: function() {
+    var parent = null, properties = $A(arguments);
+    if (Object.isFunction(properties[0]))
+      parent = properties.shift();
+
+    function klass() {
+      this.initialize.apply(this, arguments);
+    }
+
+    Object.extend(klass, Class.Methods);
+    klass.superclass = parent;
+    klass.subclasses = [];
+
+    if (parent) {
+      var subclass = function() { };
+      subclass.prototype = parent.prototype;
+      klass.prototype = new subclass;
+      parent.subclasses.push(klass);
+    }
+
+    for (var i = 0; i < properties.length; i++)
+      klass.addMethods(properties[i]);
+
+    if (!klass.prototype.initialize)
+      klass.prototype.initialize = Prototype.emptyFunction;
+
+    klass.prototype.constructor = klass;
+
+    return klass;
+  }
+};
+
+Class.Methods = {
+  addMethods: function(source) {
+    var ancestor   = this.superclass && this.superclass.prototype;
+    var properties = Object.keys(source);
+
+    if (!Object.keys({ toString: true }).length)
+      properties.push("toString", "valueOf");
+
+    for (var i = 0, length = properties.length; i < length; i++) {
+      var property = properties[i], value = source[property];
+      if (ancestor && Object.isFunction(value) &&
+          value.argumentNames().first() == "$super") {
+        var method = value;
+        value = (function(m) {
+          return function() { return ancestor[m].apply(this, arguments) };
+        })(property).wrap(method);
+
+        value.valueOf = method.valueOf.bind(method);
+        value.toString = method.toString.bind(method);
+      }
+      this.prototype[property] = value;
+    }
+
+    return this;
+  }
+};
+
+var Abstract = { };
+
+Object.extend = function(destination, source) {
+  for (var property in source)
+    destination[property] = source[property];
+  return destination;
+};
+
+Object.extend(Object, {
+  inspect: function(object) {
+    try {
+      if (Object.isUndefined(object)) return 'undefined';
+      if (object === null) return 'null';
+      return object.inspect ? object.inspect() : String(object);
+    } catch (e) {
+      if (e instanceof RangeError) return '...';
+      throw e;
+    }
+  },
+
+  toJSON: function(object) {
+    var type = typeof object;
+    switch (type) {
+      case 'undefined':
+      case 'function':
+      case 'unknown': return;
+      case 'boolean': return object.toString();
+    }
+
+    if (object === null) return 'null';
+    if (object.toJSON) return object.toJSON();
+    if (Object.isElement(object)) return;
+
+    var results = [];
+    for (var property in object) {
+      var value = Object.toJSON(object[property]);
+      if (!Object.isUndefined(value))
+        results.push(property.toJSON() + ': ' + value);
+    }
+
+    return '{' + results.join(', ') + '}';
+  },
+
+  toQueryString: function(object) {
+    return $H(object).toQueryString();
+  },
+
+  toHTML: function(object) {
+    return object && object.toHTML ? object.toHTML() : String.interpret(object);
+  },
+
+  keys: function(object) {
+    var keys = [];
+    for (var property in object)
+      keys.push(property);
+    return keys;
+  },
+
+  values: function(object) {
+    var values = [];
+    for (var property in object)
+      values.push(object[property]);
+    return values;
+  },
+
+  clone: function(object) {
+    return Object.extend({ }, object);
+  },
+
+  isElement: function(object) {
+    return !!(object && object.nodeType == 1);
+  },
+
+  isArray: function(object) {
+    return object != null && typeof object == "object" &&
+      'splice' in object && 'join' in object;
+  },
+
+  isHash: function(object) {
+    return object instanceof Hash;
+  },
+
+  isFunction: function(object) {
+    return typeof object == "function";
+  },
+
+  isString: function(object) {
+    return typeof object == "string";
+  },
+
+  isNumber: function(object) {
+    return typeof object == "number";
+  },
+
+  isUndefined: function(object) {
+    return typeof object == "undefined";
+  }
+});
+
+Object.extend(Function.prototype, {
+  argumentNames: function() {
+    var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1]
+      .replace(/\s+/g, '').split(',');
+    return names.length == 1 && !names[0] ? [] : names;
+  },
+
+  bind: function() {
+    if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+    var __method = this, args = $A(arguments), object = args.shift();
+    return function() {
+      return __method.apply(object, args.concat($A(arguments)));
+    }
+  },
+
+  bindAsEventListener: function() {
+    var __method = this, args = $A(arguments), object = args.shift();
+    return function(event) {
+      return __method.apply(object, [event || window.event].concat(args));
+    }
+  },
+
+  curry: function() {
+    if (!arguments.length) return this;
+    var __method = this, args = $A(arguments);
+    return function() {
+      return __method.apply(this, args.concat($A(arguments)));
+    }
+  },
+
+  delay: function() {
+    var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+    return window.setTimeout(function() {
+      return __method.apply(__method, args);
+    }, timeout);
+  },
+
+  defer: function() {
+    var args = [0.01].concat($A(arguments));
+    return this.delay.apply(this, args);
+  },
+
+  wrap: function(wrapper) {
+    var __method = this;
+    return function() {
+      return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+    }
+  },
+
+  methodize: function() {
+    if (this._methodized) return this._methodized;
+    var __method = this;
+    return this._methodized = function() {
+      return __method.apply(null, [this].concat($A(arguments)));
+    };
+  }
+});
+
+Date.prototype.toJSON = function() {
+  return '"' + this.getUTCFullYear() + '-' +
+    (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+    this.getUTCDate().toPaddedString(2) + 'T' +
+    this.getUTCHours().toPaddedString(2) + ':' +
+    this.getUTCMinutes().toPaddedString(2) + ':' +
+    this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
+var Try = {
+  these: function() {
+    var returnValue;
+
+    for (var i = 0, length = arguments.length; i < length; i++) {
+      var lambda = arguments[i];
+      try {
+        returnValue = lambda();
+        break;
+      } catch (e) { }
+    }
+
+    return returnValue;
+  }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+  return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+  initialize: function(callback, frequency) {
+    this.callback = callback;
+    this.frequency = frequency;
+    this.currentlyExecuting = false;
+
+    this.registerCallback();
+  },
+
+  registerCallback: function() {
+    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+  },
+
+  execute: function() {
+    this.callback(this);
+  },
+
+  stop: function() {
+    if (!this.timer) return;
+    clearInterval(this.timer);
+    this.timer = null;
+  },
+
+  onTimerEvent: function() {
+    if (!this.currentlyExecuting) {
+      try {
+        this.currentlyExecuting = true;
+        this.execute();
+      } finally {
+        this.currentlyExecuting = false;
+      }
+    }
+  }
+});
+Object.extend(String, {
+  interpret: function(value) {
+    return value == null ? '' : String(value);
+  },
+  specialChar: {
+    '\b': '\\b',
+    '\t': '\\t',
+    '\n': '\\n',
+    '\f': '\\f',
+    '\r': '\\r',
+    '\\': '\\\\'
+  }
+});
+
+Object.extend(String.prototype, {
+  gsub: function(pattern, replacement) {
+    var result = '', source = this, match;
+    replacement = arguments.callee.prepareReplacement(replacement);
+
+    while (source.length > 0) {
+      if (match = source.match(pattern)) {
+        result += source.slice(0, match.index);
+        result += String.interpret(replacement(match));
+        source  = source.slice(match.index + match[0].length);
+      } else {
+        result += source, source = '';
+      }
+    }
+    return result;
+  },
+
+  sub: function(pattern, replacement, count) {
+    replacement = this.gsub.prepareReplacement(replacement);
+    count = Object.isUndefined(count) ? 1 : count;
+
+    return this.gsub(pattern, function(match) {
+      if (--count < 0) return match[0];
+      return replacement(match);
+    });
+  },
+
+  scan: function(pattern, iterator) {
+    this.gsub(pattern, iterator);
+    return String(this);
+  },
+
+  truncate: function(length, truncation) {
+    length = length || 30;
+    truncation = Object.isUndefined(truncation) ? '...' : truncation;
+    return this.length > length ?
+      this.slice(0, length - truncation.length) + truncation : String(this);
+  },
+
+  strip: function() {
+    return this.replace(/^\s+/, '').replace(/\s+$/, '');
+  },
+
+  stripTags: function() {
+    return this.replace(/<\/?[^>]+>/gi, '');
+  },
+
+  stripScripts: function() {
+    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+  },
+
+  extractScripts: function() {
+    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+    return (this.match(matchAll) || []).map(function(scriptTag) {
+      return (scriptTag.match(matchOne) || ['', ''])[1];
+    });
+  },
+
+  evalScripts: function() {
+    return this.extractScripts().map(function(script) { return eval(script) });
+  },
+
+  escapeHTML: function() {
+    var self = arguments.callee;
+    self.text.data = this;
+    return self.div.innerHTML;
+  },
+
+  unescapeHTML: function() {
+    var div = new Element('div');
+    div.innerHTML = this.stripTags();
+    return div.childNodes[0] ? (div.childNodes.length > 1 ?
+      $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+      div.childNodes[0].nodeValue) : '';
+  },
+
+  toQueryParams: function(separator) {
+    var match = this.strip().match(/([^?#]*)(#.*)?$/);
+    if (!match) return { };
+
+    return match[1].split(separator || '&').inject({ }, function(hash, pair) {
+      if ((pair = pair.split('='))[0]) {
+        var key = decodeURIComponent(pair.shift());
+        var value = pair.length > 1 ? pair.join('=') : pair[0];
+        if (value != undefined) value = decodeURIComponent(value);
+
+        if (key in hash) {
+          if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+          hash[key].push(value);
+        }
+        else hash[key] = value;
+      }
+      return hash;
+    });
+  },
+
+  toArray: function() {
+    return this.split('');
+  },
+
+  succ: function() {
+    return this.slice(0, this.length - 1) +
+      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+  },
+
+  times: function(count) {
+    return count < 1 ? '' : new Array(count + 1).join(this);
+  },
+
+  camelize: function() {
+    var parts = this.split('-'), len = parts.length;
+    if (len == 1) return parts[0];
+
+    var camelized = this.charAt(0) == '-'
+      ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+      : parts[0];
+
+    for (var i = 1; i < len; i++)
+      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+    return camelized;
+  },
+
+  capitalize: function() {
+    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+  },
+
+  underscore: function() {
+    return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+  },
+
+  dasherize: function() {
+    return this.gsub(/_/,'-');
+  },
+
+  inspect: function(useDoubleQuotes) {
+    var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+      var character = String.specialChar[match[0]];
+      return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+    });
+    if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+    return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+  },
+
+  toJSON: function() {
+    return this.inspect(true);
+  },
+
+  unfilterJSON: function(filter) {
+    return this.sub(filter || Prototype.JSONFilter, '#{1}');
+  },
+
+  isJSON: function() {
+    var str = this;
+    if (str.blank()) return false;
+    str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+    return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+  },
+
+  evalJSON: function(sanitize) {
+    var json = this.unfilterJSON();
+    try {
+      if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+    } catch (e) { }
+    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+  },
+
+  include: function(pattern) {
+    return this.indexOf(pattern) > -1;
+  },
+
+  startsWith: function(pattern) {
+    return this.indexOf(pattern) === 0;
+  },
+
+  endsWith: function(pattern) {
+    var d = this.length - pattern.length;
+    return d >= 0 && this.lastIndexOf(pattern) === d;
+  },
+
+  empty: function() {
+    return this == '';
+  },
+
+  blank: function() {
+    return /^\s*$/.test(this);
+  },
+
+  interpolate: function(object, pattern) {
+    return new Template(this, pattern).evaluate(object);
+  }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+  escapeHTML: function() {
+    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+  },
+  unescapeHTML: function() {
+    return this.stripTags().replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
+  }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+  if (Object.isFunction(replacement)) return replacement;
+  var template = new Template(replacement);
+  return function(match) { return template.evaluate(match) };
+};
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+  div:  document.createElement('div'),
+  text: document.createTextNode('')
+});
+
+String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text);
+
+var Template = Class.create({
+  initialize: function(template, pattern) {
+    this.template = template.toString();
+    this.pattern = pattern || Template.Pattern;
+  },
+
+  evaluate: function(object) {
+    if (Object.isFunction(object.toTemplateReplacements))
+      object = object.toTemplateReplacements();
+
+    return this.template.gsub(this.pattern, function(match) {
+      if (object == null) return '';
+
+      var before = match[1] || '';
+      if (before == '\\') return match[2];
+
+      var ctx = object, expr = match[3];
+      var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
+      match = pattern.exec(expr);
+      if (match == null) return before;
+
+      while (match != null) {
+        var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+        ctx = ctx[comp];
+        if (null == ctx || '' == match[3]) break;
+        expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+        match = pattern.exec(expr);
+      }
+
+      return before + String.interpret(ctx);
+    });
+  }
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+
+var $break = { };
+
+var Enumerable = {
+  each: function(iterator, context) {
+    var index = 0;
+    try {
+      this._each(function(value) {
+        iterator.call(context, value, index++);
+      });
+    } catch (e) {
+      if (e != $break) throw e;
+    }
+    return this;
+  },
+
+  eachSlice: function(number, iterator, context) {
+    var index = -number, slices = [], array = this.toArray();
+    if (number < 1) return array;
+    while ((index += number) < array.length)
+      slices.push(array.slice(index, index+number));
+    return slices.collect(iterator, context);
+  },
+
+  all: function(iterator, context) {
+    iterator = iterator || Prototype.K;
+    var result = true;
+    this.each(function(value, index) {
+      result = result && !!iterator.call(context, value, index);
+      if (!result) throw $break;
+    });
+    return result;
+  },
+
+  any: function(iterator, context) {
+    iterator = iterator || Prototype.K;
+    var result = false;
+    this.each(function(value, index) {
+      if (result = !!iterator.call(context, value, index))
+        throw $break;
+    });
+    return result;
+  },
+
+  collect: function(iterator, context) {
+    iterator = iterator || Prototype.K;
+    var results = [];
+    this.each(function(value, index) {
+      results.push(iterator.call(context, value, index));
+    });
+    return results;
+  },
+
+  detect: function(iterator, context) {
+    var result;
+    this.each(function(value, index) {
+      if (iterator.call(context, value, index)) {
+        result = value;
+        throw $break;
+      }
+    });
+    return result;
+  },
+
+  findAll: function(iterator, context) {
+    var results = [];
+    this.each(function(value, index) {
+      if (iterator.call(context, value, index))
+        results.push(value);
+    });
+    return results;
+  },
+
+  grep: function(filter, iterator, context) {
+    iterator = iterator || Prototype.K;
+    var results = [];
+
+    if (Object.isString(filter))
+      filter = new RegExp(filter);
+
+    this.each(function(value, index) {
+      if (filter.match(value))
+        results.push(iterator.call(context, value, index));
+    });
+    return results;
+  },
+
+  include: function(object) {
+    if (Object.isFunction(this.indexOf))
+      if (this.indexOf(object) != -1) return true;
+
+    var found = false;
+    this.each(function(value) {
+      if (value == object) {
+        found = true;
+        throw $break;
+      }
+    });
+    return found;
+  },
+
+  inGroupsOf: function(number, fillWith) {
+    fillWith = Object.isUndefined(fillWith) ? null : fillWith;
+    return this.eachSlice(number, function(slice) {
+      while(slice.length < number) slice.push(fillWith);
+      return slice;
+    });
+  },
+
+  inject: function(memo, iterator, context) {
+    this.each(function(value, index) {
+      memo = iterator.call(context, memo, value, index);
+    });
+    return memo;
+  },
+
+  invoke: function(method) {
+    var args = $A(arguments).slice(1);
+    return this.map(function(value) {
+      return value[method].apply(value, args);
+    });
+  },
+
+  max: function(iterator, context) {
+    iterator = iterator || Prototype.K;
+    var result;
+    this.each(function(value, index) {
+      value = iterator.call(context, value, index);
+      if (result == null || value >= result)
+        result = value;
+    });
+    return result;
+  },
+
+  min: function(iterator, context) {
+    iterator = iterator || Prototype.K;
+    var result;
+    this.each(function(value, index) {
+      value = iterator.call(context, value, index);
+      if (result == null || value < result)
+        result = value;
+    });
+    return result;
+  },
+
+  partition: function(iterator, context) {
+    iterator = iterator || Prototype.K;
+    var trues = [], falses = [];
+    this.each(function(value, index) {
+      (iterator.call(context, value, index) ?
+        trues : falses).push(value);
+    });
+    return [trues, falses];
+  },
+
+  pluck: function(property) {
+    var results = [];
+    this.each(function(value) {
+      results.push(value[property]);
+    });
+    return results;
+  },
+
+  reject: function(iterator, context) {
+    var results = [];
+    this.each(function(value, index) {
+      if (!iterator.call(context, value, index))
+        results.push(value);
+    });
+    return results;
+  },
+
+  sortBy: function(iterator, context) {
+    return this.map(function(value, index) {
+      return {
+        value: value,
+        criteria: iterator.call(context, value, index)
+      };
+    }).sort(function(left, right) {
+      var a = left.criteria, b = right.criteria;
+      return a < b ? -1 : a > b ? 1 : 0;
+    }).pluck('value');
+  },
+
+  toArray: function() {
+    return this.map();
+  },
+
+  zip: function() {
+    var iterator = Prototype.K, args = $A(arguments);
+    if (Object.isFunction(args.last()))
+      iterator = args.pop();
+
+    var collections = [this].concat(args).map($A);
+    return this.map(function(value, index) {
+      return iterator(collections.pluck(index));
+    });
+  },
+
+  size: function() {
+    return this.toArray().length;
+  },
+
+  inspect: function() {
+    return '#<Enumerable:' + this.toArray().inspect() + '>';
+  }
+};
+
+Object.extend(Enumerable, {
+  map:     Enumerable.collect,
+  find:    Enumerable.detect,
+  select:  Enumerable.findAll,
+  filter:  Enumerable.findAll,
+  member:  Enumerable.include,
+  entries: Enumerable.toArray,
+  every:   Enumerable.all,
+  some:    Enumerable.any
+});
+function $A(iterable) {
+  if (!iterable) return [];
+  if (iterable.toArray) return iterable.toArray();
+  var length = iterable.length || 0, results = new Array(length);
+  while (length--) results[length] = iterable[length];
+  return results;
+}
+
+if (Prototype.Browser.WebKit) {
+  $A = function(iterable) {
+    if (!iterable) return [];
+    // In Safari, only use the `toArray` method if it's not a NodeList.
+    // A NodeList is a function, has an function `item` property, and a numeric
+    // `length` property. Adapted from Google Doctype.
+    if (!(typeof iterable === 'function' && typeof iterable.length ===
+        'number' && typeof iterable.item === 'function') && iterable.toArray)
+      return iterable.toArray();
+    var length = iterable.length || 0, results = new Array(length);
+    while (length--) results[length] = iterable[length];
+    return results;
+  };
+}
+
+Array.from = $A;
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+  _each: function(iterator) {
+    for (var i = 0, length = this.length; i < length; i++)
+      iterator(this[i]);
+  },
+
+  clear: function() {
+    this.length = 0;
+    return this;
+  },
+
+  first: function() {
+    return this[0];
+  },
+
+  last: function() {
+    return this[this.length - 1];
+  },
+
+  compact: function() {
+    return this.select(function(value) {
+      return value != null;
+    });
+  },
+
+  flatten: function() {
+    return this.inject([], function(array, value) {
+      return array.concat(Object.isArray(value) ?
+        value.flatten() : [value]);
+    });
+  },
+
+  without: function() {
+    var values = $A(arguments);
+    return this.select(function(value) {
+      return !values.include(value);
+    });
+  },
+
+  reverse: function(inline) {
+    return (inline !== false ? this : this.toArray())._reverse();
+  },
+
+  reduce: function() {
+    return this.length > 1 ? this : this[0];
+  },
+
+  uniq: function(sorted) {
+    return this.inject([], function(array, value, index) {
+      if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+        array.push(value);
+      return array;
+    });
+  },
+
+  intersect: function(array) {
+    return this.uniq().findAll(function(item) {
+      return array.detect(function(value) { return item === value });
+    });
+  },
+
+  clone: function() {
+    return [].concat(this);
+  },
+
+  size: function() {
+    return this.length;
+  },
+
+  inspect: function() {
+    return '[' + this.map(Object.inspect).join(', ') + ']';
+  },
+
+  toJSON: function() {
+    var results = [];
+    this.each(function(object) {
+      var value = Object.toJSON(object);
+      if (!Object.isUndefined(value)) results.push(value);
+    });
+    return '[' + results.join(', ') + ']';
+  }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+  Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+  i || (i = 0);
+  var length = this.length;
+  if (i < 0) i = length + i;
+  for (; i < length; i++)
+    if (this[i] === item) return i;
+  return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+  i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+  var n = this.slice(0, i).reverse().indexOf(item);
+  return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+  if (!Object.isString(string)) return [];
+  string = string.strip();
+  return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+  Array.prototype.concat = function() {
+    var array = [];
+    for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+    for (var i = 0, length = arguments.length; i < length; i++) {
+      if (Object.isArray(arguments[i])) {
+        for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+          array.push(arguments[i][j]);
+      } else {
+        array.push(arguments[i]);
+      }
+    }
+    return array;
+  };
+}
+Object.extend(Number.prototype, {
+  toColorPart: function() {
+    return this.toPaddedString(2, 16);
+  },
+
+  succ: function() {
+    return this + 1;
+  },
+
+  times: function(iterator, context) {
+    $R(0, this, true).each(iterator, context);
+    return this;
+  },
+
+  toPaddedString: function(length, radix) {
+    var string = this.toString(radix || 10);
+    return '0'.times(length - string.length) + string;
+  },
+
+  toJSON: function() {
+    return isFinite(this) ? this.toString() : 'null';
+  }
+});
+
+$w('abs round ceil floor').each(function(method){
+  Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+  return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+
+  function toQueryPair(key, value) {
+    if (Object.isUndefined(value)) return key;
+    return key + '=' + encodeURIComponent(String.interpret(value));
+  }
+
+  return {
+    initialize: function(object) {
+      this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+    },
+
+    _each: function(iterator) {
+      for (var key in this._object) {
+        var value = this._object[key], pair = [key, value];
+        pair.key = key;
+        pair.value = value;
+        iterator(pair);
+      }
+    },
+
+    set: function(key, value) {
+      return this._object[key] = value;
+    },
+
+    get: function(key) {
+      // simulating poorly supported hasOwnProperty
+      if (this._object[key] !== Object.prototype[key])
+        return this._object[key];
+    },
+
+    unset: function(key) {
+      var value = this._object[key];
+      delete this._object[key];
+      return value;
+    },
+
+    toObject: function() {
+      return Object.clone(this._object);
+    },
+
+    keys: function() {
+      return this.pluck('key');
+    },
+
+    values: function() {
+      return this.pluck('value');
+    },
+
+    index: function(value) {
+      var match = this.detect(function(pair) {
+        return pair.value === value;
+      });
+      return match && match.key;
+    },
+
+    merge: function(object) {
+      return this.clone().update(object);
+    },
+
+    update: function(object) {
+      return new Hash(object).inject(this, function(result, pair) {
+        result.set(pair.key, pair.value);
+        return result;
+      });
+    },
+
+    toQueryString: function() {
+      return this.inject([], function(results, pair) {
+        var key = encodeURIComponent(pair.key), values = pair.value;
+
+        if (values && typeof values == 'object') {
+          if (Object.isArray(values))
+            return results.concat(values.map(toQueryPair.curry(key)));
+        } else results.push(toQueryPair(key, values));
+        return results;
+      }).join('&');
+    },
+
+    inspect: function() {
+      return '#<Hash:{' + this.map(function(pair) {
+        return pair.map(Object.inspect).join(': ');
+      }).join(', ') + '}>';
+    },
+
+    toJSON: function() {
+      return Object.toJSON(this.toObject());
+    },
+
+    clone: function() {
+      return new Hash(this);
+    }
+  }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
+  initialize: function(start, end, exclusive) {
+    this.start = start;
+    this.end = end;
+    this.exclusive = exclusive;
+  },
+
+  _each: function(iterator) {
+    var value = this.start;
+    while (this.include(value)) {
+      iterator(value);
+      value = value.succ();
+    }
+  },
+
+  include: function(value) {
+    if (value < this.start)
+      return false;
+    if (this.exclusive)
+      return value < this.end;
+    return value <= this.end;
+  }
+});
+
+var $R = function(start, end, exclusive) {
+  return new ObjectRange(start, end, exclusive);
+};
+
+var Ajax = {
+  getTransport: function() {
+    return Try.these(
+      function() {return new XMLHttpRequest()},
+      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+      function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+    ) || false;
+  },
+
+  activeRequestCount: 0
+};
+
+Ajax.Responders = {
+  responders: [],
+
+  _each: function(iterator) {
+    this.responders._each(iterator);
+  },
+
+  register: function(responder) {
+    if (!this.include(responder))
+      this.responders.push(responder);
+  },
+
+  unregister: function(responder) {
+    this.responders = this.responders.without(responder);
+  },
+
+  dispatch: function(callback, request, transport, json) {
+    this.each(function(responder) {
+      if (Object.isFunction(responder[callback])) {
+        try {
+          responder[callback].apply(responder, [request, transport, json]);
+        } catch (e) { }
+      }
+    });
+  }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+  onCreate:   function() { Ajax.activeRequestCount++ },
+  onComplete: function() { Ajax.activeRequestCount-- }
+});
+
+Ajax.Base = Class.create({
+  initialize: function(options) {
+    this.options = {
+      method:       'post',
+      asynchronous: true,
+      contentType:  'application/x-www-form-urlencoded',
+      encoding:     'UTF-8',
+      parameters:   '',
+      evalJSON:     true,
+      evalJS:       true
+    };
+    Object.extend(this.options, options || { });
+
+    this.options.method = this.options.method.toLowerCase();
+
+    if (Object.isString(this.options.parameters))
+      this.options.parameters = this.options.parameters.toQueryParams();
+    else if (Object.isHash(this.options.parameters))
+      this.options.parameters = this.options.parameters.toObject();
+  }
+});
+
+Ajax.Request = Class.create(Ajax.Base, {
+  _complete: false,
+
+  initialize: function($super, url, options) {
+    $super(options);
+    this.transport = Ajax.getTransport();
+    this.request(url);
+  },
+
+  request: function(url) {
+    this.url = url;
+    this.method = this.options.method;
+    var params = Object.clone(this.options.parameters);
+
+    if (!['get', 'post'].include(this.method)) {
+      // simulate other verbs over post
+      params['_method'] = this.method;
+      this.method = 'post';
+    }
+
+    this.parameters = params;
+
+    if (params = Object.toQueryString(params)) {
+      // when GET, append parameters to URL
+      if (this.method == 'get')
+        this.url += (this.url.include('?') ? '&' : '?') + params;
+      else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+        params += '&_=';
+    }
+
+    try {
+      var response = new Ajax.Response(this);
+      if (this.options.onCreate) this.options.onCreate(response);
+      Ajax.Responders.dispatch('onCreate', this, response);
+
+      this.transport.open(this.method.toUpperCase(), this.url,
+        this.options.asynchronous);
+
+      if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+      this.transport.onreadystatechange = this.onStateChange.bind(this);
+      this.setRequestHeaders();
+
+      this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+      this.transport.send(this.body);
+
+      /* Force Firefox to handle ready state 4 for synchronous requests */
+      if (!this.options.asynchronous && this.transport.overrideMimeType)
+        this.onStateChange();
+
+    }
+    catch (e) {
+      this.dispatchException(e);
+    }
+  },
+
+  onStateChange: function() {
+    var readyState = this.transport.readyState;
+    if (readyState > 1 && !((readyState == 4) && this._complete))
+      this.respondToReadyState(this.transport.readyState);
+  },
+
+  setRequestHeaders: function() {
+    var headers = {
+      'X-Requested-With': 'XMLHttpRequest',
+      'X-Prototype-Version': Prototype.Version,
+      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+    };
+
+    if (this.method == 'post') {
+      headers['Content-type'] = this.options.contentType +
+        (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+      /* Force "Connection: close" for older Mozilla browsers to work
+       * around a bug where XMLHttpRequest sends an incorrect
+       * Content-length header. See Mozilla Bugzilla #246651.
+       */
+      if (this.transport.overrideMimeType &&
+          (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+            headers['Connection'] = 'close';
+    }
+
+    // user-defined headers
+    if (typeof this.options.requestHeaders == 'object') {
+      var extras = this.options.requestHeaders;
+
+      if (Object.isFunction(extras.push))
+        for (var i = 0, length = extras.length; i < length; i += 2)
+          headers[extras[i]] = extras[i+1];
+      else
+        $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+    }
+
+    for (var name in headers)
+      this.transport.setRequestHeader(name, headers[name]);
+  },
+
+  success: function() {
+    var status = this.getStatus();
+    return !status || (status >= 200 && status < 300);
+  },
+
+  getStatus: function() {
+    try {
+      return this.transport.status || 0;
+    } catch (e) { return 0 }
+  },
+
+  respondToReadyState: function(readyState) {
+    var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+    if (state == 'Complete') {
+      try {
+        this._complete = true;
+        (this.options['on' + response.status]
+         || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+         || Prototype.emptyFunction)(response, response.headerJSON);
+      } catch (e) {
+        this.dispatchException(e);
+      }
+
+      var contentType = response.getHeader('Content-type');
+      if (this.options.evalJS == 'force'
+          || (this.options.evalJS && this.isSameOrigin() && contentType
+          && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+        this.evalResponse();
+    }
+
+    try {
+      (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+      Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+    } catch (e) {
+      this.dispatchException(e);
+    }
+
+    if (state == 'Complete') {
+      // avoid memory leak in MSIE: clean up
+      this.transport.onreadystatechange = Prototype.emptyFunction;
+    }
+  },
+
+  isSameOrigin: function() {
+    var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+    return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+      protocol: location.protocol,
+      domain: document.domain,
+      port: location.port ? ':' + location.port : ''
+    }));
+  },
+
+  getHeader: function(name) {
+    try {
+      return this.transport.getResponseHeader(name) || null;
+    } catch (e) { return null }
+  },
+
+  evalResponse: function() {
+    try {
+      return eval((this.transport.responseText || '').unfilterJSON());
+    } catch (e) {
+      this.dispatchException(e);
+    }
+  },
+
+  dispatchException: function(exception) {
+    (this.options.onException || Prototype.emptyFunction)(this, exception);
+    Ajax.Responders.dispatch('onException', this, exception);
+  }
+});
+
+Ajax.Request.Events =
+  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Response = Class.create({
+  initialize: function(request){
+    this.request = request;
+    var transport  = this.transport  = request.transport,
+        readyState = this.readyState = transport.readyState;
+
+    if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+      this.status       = this.getStatus();
+      this.statusText   = this.getStatusText();
+      this.responseText = String.interpret(transport.responseText);
+      this.headerJSON   = this._getHeaderJSON();
+    }
+
+    if(readyState == 4) {
+      var xml = transport.responseXML;
+      this.responseXML  = Object.isUndefined(xml) ? null : xml;
+      this.responseJSON = this._getResponseJSON();
+    }
+  },
+
+  status:      0,
+  statusText: '',
+
+  getStatus: Ajax.Request.prototype.getStatus,
+
+  getStatusText: function() {
+    try {
+      return this.transport.statusText || '';
+    } catch (e) { return '' }
+  },
+
+  getHeader: Ajax.Request.prototype.getHeader,
+
+  getAllHeaders: function() {
+    try {
+      return this.getAllResponseHeaders();
+    } catch (e) { return null }
+  },
+
+  getResponseHeader: function(name) {
+    return this.transport.getResponseHeader(name);
+  },
+
+  getAllResponseHeaders: function() {
+    return this.transport.getAllResponseHeaders();
+  },
+
+  _getHeaderJSON: function() {
+    var json = this.getHeader('X-JSON');
+    if (!json) return null;
+    json = decodeURIComponent(escape(json));
+    try {
+      return json.evalJSON(this.request.options.sanitizeJSON ||
+        !this.request.isSameOrigin());
+    } catch (e) {
+      this.request.dispatchException(e);
+    }
+  },
+
+  _getResponseJSON: function() {
+    var options = this.request.options;
+    if (!options.evalJSON || (options.evalJSON != 'force' &&
+      !(this.getHeader('Content-type') || '').include('application/json')) ||
+        this.responseText.blank())
+          return null;
+    try {
+      return this.responseText.evalJSON(options.sanitizeJSON ||
+        !this.request.isSameOrigin());
+    } catch (e) {
+      this.request.dispatchException(e);
+    }
+  }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+  initialize: function($super, container, url, options) {
+    this.container = {
+      success: (container.success || container),
+      failure: (container.failure || (container.success ? null : container))
+    };
+
+    options = Object.clone(options);
+    var onComplete = options.onComplete;
+    options.onComplete = (function(response, json) {
+      this.updateContent(response.responseText);
+      if (Object.isFunction(onComplete)) onComplete(response, json);
+    }).bind(this);
+
+    $super(url, options);
+  },
+
+  updateContent: function(responseText) {
+    var receiver = this.container[this.success() ? 'success' : 'failure'],
+        options = this.options;
+
+    if (!options.evalScripts) responseText = responseText.stripScripts();
+
+    if (receiver = $(receiver)) {
+      if (options.insertion) {
+        if (Object.isString(options.insertion)) {
+          var insertion = { }; insertion[options.insertion] = responseText;
+          receiver.insert(insertion);
+        }
+        else options.insertion(receiver, responseText);
+      }
+      else receiver.update(responseText);
+    }
+  }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+  initialize: function($super, container, url, options) {
+    $super(options);
+    this.onComplete = this.options.onComplete;
+
+    this.frequency = (this.options.frequency || 2);
+    this.decay = (this.options.decay || 1);
+
+    this.updater = { };
+    this.container = container;
+    this.url = url;
+
+    this.start();
+  },
+
+  start: function() {
+    this.options.onComplete = this.updateComplete.bind(this);
+    this.onTimerEvent();
+  },
+
+  stop: function() {
+    this.updater.options.onComplete = undefined;
+    clearTimeout(this.timer);
+    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+  },
+
+  updateComplete: function(response) {
+    if (this.options.decay) {
+      this.decay = (response.responseText == this.lastText ?
+        this.decay * this.options.decay : 1);
+
+      this.lastText = response.responseText;
+    }
+    this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
+  },
+
+  onTimerEvent: function() {
+    this.updater = new Ajax.Updater(this.container, this.url, this.options);
+  }
+});
+function $(element) {
+  if (arguments.length > 1) {
+    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+      elements.push($(arguments[i]));
+    return elements;
+  }
+  if (Object.isString(element))
+    element = document.getElementById(element);
+  return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+  document._getElementsByXPath = function(expression, parentElement) {
+    var results = [];
+    var query = document.evaluate(expression, $(parentElement) || document,
+      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+    for (var i = 0, length = query.snapshotLength; i < length; i++)
+      results.push(Element.extend(query.snapshotItem(i)));
+    return results;
+  };
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Node) var Node = { };
+
+if (!Node.ELEMENT_NODE) {
+  // DOM level 2 ECMAScript Language Binding
+  Object.extend(Node, {
+    ELEMENT_NODE: 1,
+    ATTRIBUTE_NODE: 2,
+    TEXT_NODE: 3,
+    CDATA_SECTION_NODE: 4,
+    ENTITY_REFERENCE_NODE: 5,
+    ENTITY_NODE: 6,
+    PROCESSING_INSTRUCTION_NODE: 7,
+    COMMENT_NODE: 8,
+    DOCUMENT_NODE: 9,
+    DOCUMENT_TYPE_NODE: 10,
+    DOCUMENT_FRAGMENT_NODE: 11,
+    NOTATION_NODE: 12
+  });
+}
+
+(function() {
+  var element = this.Element;
+  this.Element = function(tagName, attributes) {
+    attributes = attributes || { };
+    tagName = tagName.toLowerCase();
+    var cache = Element.cache;
+    if (Prototype.Browser.IE && attributes.name) {
+      tagName = '<' + tagName + ' name="' + attributes.name + '">';
+      delete attributes.name;
+      return Element.writeAttribute(document.createElement(tagName), attributes);
+    }
+    if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+    return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+  };
+  Object.extend(this.Element, element || { });
+  if (element) this.Element.prototype = element.prototype;
+}).call(window);
+
+Element.cache = { };
+
+Element.Methods = {
+  visible: function(element) {
+    return $(element).style.display != 'none';
+  },
+
+  toggle: function(element) {
+    element = $(element);
+    Element[Element.visible(element) ? 'hide' : 'show'](element);
+    return element;
+  },
+
+  hide: function(element) {
+    element = $(element);
+    element.style.display = 'none';
+    return element;
+  },
+
+  show: function(element) {
+    element = $(element);
+    element.style.display = '';
+    return element;
+  },
+
+  remove: function(element) {
+    element = $(element);
+    element.parentNode.removeChild(element);
+    return element;
+  },
+
+  update: function(element, content) {
+    element = $(element);
+    if (content && content.toElement) content = content.toElement();
+    if (Object.isElement(content)) return element.update().insert(content);
+    content = Object.toHTML(content);
+    element.innerHTML = content.stripScripts();
+    content.evalScripts.bind(content).defer();
+    return element;
+  },
+
+  replace: function(element, content) {
+    element = $(element);
+    if (content && content.toElement) content = content.toElement();
+    else if (!Object.isElement(content)) {
+      content = Object.toHTML(content);
+      var range = element.ownerDocument.createRange();
+      range.selectNode(element);
+      content.evalScripts.bind(content).defer();
+      content = range.createContextualFragment(content.stripScripts());
+    }
+    element.parentNode.replaceChild(content, element);
+    return element;
+  },
+
+  insert: function(element, insertions) {
+    element = $(element);
+
+    if (Object.isString(insertions) || Object.isNumber(insertions) ||
+        Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+          insertions = {bottom:insertions};
+
+    var content, insert, tagName, childNodes;
+
+    for (var position in insertions) {
+      content  = insertions[position];
+      position = position.toLowerCase();
+      insert = Element._insertionTranslations[position];
+
+      if (content && content.toElement) content = content.toElement();
+      if (Object.isElement(content)) {
+        insert(element, content);
+        continue;
+      }
+
+      content = Object.toHTML(content);
+
+      tagName = ((position == 'before' || position == 'after')
+        ? element.parentNode : element).tagName.toUpperCase();
+
+      childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+      if (position == 'top' || position == 'after') childNodes.reverse();
+      childNodes.each(insert.curry(element));
+
+      content.evalScripts.bind(content).defer();
+    }
+
+    return element;
+  },
+
+  wrap: function(element, wrapper, attributes) {
+    element = $(element);
+    if (Object.isElement(wrapper))
+      $(wrapper).writeAttribute(attributes || { });
+    else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+    else wrapper = new Element('div', wrapper);
+    if (element.parentNode)
+      element.parentNode.replaceChild(wrapper, element);
+    wrapper.appendChild(element);
+    return wrapper;
+  },
+
+  inspect: function(element) {
+    element = $(element);
+    var result = '<' + element.tagName.toLowerCase();
+    $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+      var property = pair.first(), attribute = pair.last();
+      var value = (element[property] || '').toString();
+      if (value) result += ' ' + attribute + '=' + value.inspect(true);
+    });
+    return result + '>';
+  },
+
+  recursivelyCollect: function(element, property) {
+    element = $(element);
+    var elements = [];
+    while (element = element[property])
+      if (element.nodeType == 1)
+        elements.push(Element.extend(element));
+    return elements;
+  },
+
+  ancestors: function(element) {
+    return $(element).recursivelyCollect('parentNode');
+  },
+
+  descendants: function(element) {
+    return $(element).select("*");
+  },
+
+  firstDescendant: function(element) {
+    element = $(element).firstChild;
+    while (element && element.nodeType != 1) element = element.nextSibling;
+    return $(element);
+  },
+
+  immediateDescendants: function(element) {
+    if (!(element = $(element).firstChild)) return [];
+    while (element && element.nodeType != 1) element = element.nextSibling;
+    if (element) return [element].concat($(element).nextSiblings());
+    return [];
+  },
+
+  previousSiblings: function(element) {
+    return $(element).recursivelyCollect('previousSibling');
+  },
+
+  nextSiblings: function(element) {
+    return $(element).recursivelyCollect('nextSibling');
+  },
+
+  siblings: function(element) {
+    element = $(element);
+    return element.previousSiblings().reverse().concat(element.nextSiblings());
+  },
+
+  match: function(element, selector) {
+    if (Object.isString(selector))
+      selector = new Selector(selector);
+    return selector.match($(element));
+  },
+
+  up: function(element, expression, index) {
+    element = $(element);
+    if (arguments.length == 1) return $(element.parentNode);
+    var ancestors = element.ancestors();
+    return Object.isNumber(expression) ? ancestors[expression] :
+      Selector.findElement(ancestors, expression, index);
+  },
+
+  down: function(element, expression, index) {
+    element = $(element);
+    if (arguments.length == 1) return element.firstDescendant();
+    return Object.isNumber(expression) ? element.descendants()[expression] :
+      Element.select(element, expression)[index || 0];
+  },
+
+  previous: function(element, expression, index) {
+    element = $(element);
+    if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+    var previousSiblings = element.previousSiblings();
+    return Object.isNumber(expression) ? previousSiblings[expression] :
+      Selector.findElement(previousSiblings, expression, index);
+  },
+
+  next: function(element, expression, index) {
+    element = $(element);
+    if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+    var nextSiblings = element.nextSiblings();
+    return Object.isNumber(expression) ? nextSiblings[expression] :
+      Selector.findElement(nextSiblings, expression, index);
+  },
+
+  select: function() {
+    var args = $A(arguments), element = $(args.shift());
+    return Selector.findChildElements(element, args);
+  },
+
+  adjacent: function() {
+    var args = $A(arguments), element = $(args.shift());
+    return Selector.findChildElements(element.parentNode, args).without(element);
+  },
+
+  identify: function(element) {
+    element = $(element);
+    var id = element.readAttribute('id'), self = arguments.callee;
+    if (id) return id;
+    do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+    element.writeAttribute('id', id);
+    return id;
+  },
+
+  readAttribute: function(element, name) {
+    element = $(element);
+    if (Prototype.Browser.IE) {
+      var t = Element._attributeTranslations.read;
+      if (t.values[name]) return t.values[name](element, name);
+      if (t.names[name]) name = t.names[name];
+      if (name.include(':')) {
+        return (!element.attributes || !element.attributes[name]) ? null :
+         element.attributes[name].value;
+      }
+    }
+    return element.getAttribute(name);
+  },
+
+  writeAttribute: function(element, name, value) {
+    element = $(element);
+    var attributes = { }, t = Element._attributeTranslations.write;
+
+    if (typeof name == 'object') attributes = name;
+    else attributes[name] = Object.isUndefined(value) ? true : value;
+
+    for (var attr in attributes) {
+      name = t.names[attr] || attr;
+      value = attributes[attr];
+      if (t.values[attr]) name = t.values[attr](element, value);
+      if (value === false || value === null)
+        element.removeAttribute(name);
+      else if (value === true)
+        element.setAttribute(name, name);
+      else element.setAttribute(name, value);
+    }
+    return element;
+  },
+
+  getHeight: function(element) {
+    return $(element).getDimensions().height;
+  },
+
+  getWidth: function(element) {
+    return $(element).getDimensions().width;
+  },
+
+  classNames: function(element) {
+    return new Element.ClassNames(element);
+  },
+
+  hasClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    var elementClassName = element.className;
+    return (elementClassName.length > 0 && (elementClassName == className ||
+      new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
+  },
+
+  addClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    if (!element.hasClassName(className))
+      element.className += (element.className ? ' ' : '') + className;
+    return element;
+  },
+
+  removeClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    element.className = element.className.replace(
+      new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+    return element;
+  },
+
+  toggleClassName: function(element, className) {
+    if (!(element = $(element))) return;
+    return element[element.hasClassName(className) ?
+      'removeClassName' : 'addClassName'](className);
+  },
+
+  // removes whitespace-only text node children
+  cleanWhitespace: function(element) {
+    element = $(element);
+    var node = element.firstChild;
+    while (node) {
+      var nextNode = node.nextSibling;
+      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+        element.removeChild(node);
+      node = nextNode;
+    }
+    return element;
+  },
+
+  empty: function(element) {
+    return $(element).innerHTML.blank();
+  },
+
+  descendantOf: function(element, ancestor) {
+    element = $(element), ancestor = $(ancestor);
+
+    if (element.compareDocumentPosition)
+      return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+    if (ancestor.contains)
+      return ancestor.contains(element) && ancestor !== element;
+
+    while (element = element.parentNode)
+      if (element == ancestor) return true;
+
+    return false;
+  },
+
+  scrollTo: function(element) {
+    element = $(element);
+    var pos = element.cumulativeOffset();
+    window.scrollTo(pos[0], pos[1]);
+    return element;
+  },
+
+  getStyle: function(element, style) {
+    element = $(element);
+    style = style == 'float' ? 'cssFloat' : style.camelize();
+    var value = element.style[style];
+    if (!value || value == 'auto') {
+      var css = document.defaultView.getComputedStyle(element, null);
+      value = css ? css[style] : null;
+    }
+    if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+    return value == 'auto' ? null : value;
+  },
+
+  getOpacity: function(element) {
+    return $(element).getStyle('opacity');
+  },
+
+  setStyle: function(element, styles) {
+    element = $(element);
+    var elementStyle = element.style, match;
+    if (Object.isString(styles)) {
+      element.style.cssText += ';' + styles;
+      return styles.include('opacity') ?
+        element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+    }
+    for (var property in styles)
+      if (property == 'opacity') element.setOpacity(styles[property]);
+      else
+        elementStyle[(property == 'float' || property == 'cssFloat') ?
+          (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
+            property] = styles[property];
+
+    return element;
+  },
+
+  setOpacity: function(element, value) {
+    element = $(element);
+    element.style.opacity = (value == 1 || value === '') ? '' :
+      (value < 0.00001) ? 0 : value;
+    return element;
+  },
+
+  getDimensions: function(element) {
+    element = $(element);
+    var display = element.getStyle('display');
+    if (display != 'none' && display != null) // Safari bug
+      return {width: element.offsetWidth, height: element.offsetHeight};
+
+    // All *Width and *Height properties give 0 on elements with display none,
+    // so enable the element temporarily
+    var els = element.style;
+    var originalVisibility = els.visibility;
+    var originalPosition = els.position;
+    var originalDisplay = els.display;
+    els.visibility = 'hidden';
+    els.position = 'absolute';
+    els.display = 'block';
+    var originalWidth = element.clientWidth;
+    var originalHeight = element.clientHeight;
+    els.display = originalDisplay;
+    els.position = originalPosition;
+    els.visibility = originalVisibility;
+    return {width: originalWidth, height: originalHeight};
+  },
+
+  makePositioned: function(element) {
+    element = $(element);
+    var pos = Element.getStyle(element, 'position');
+    if (pos == 'static' || !pos) {
+      element._madePositioned = true;
+      element.style.position = 'relative';
+      // Opera returns the offset relative to the positioning context, when an
+      // element is position relative but top and left have not been defined
+      if (Prototype.Browser.Opera) {
+        element.style.top = 0;
+        element.style.left = 0;
+      }
+    }
+    return element;
+  },
+
+  undoPositioned: function(element) {
+    element = $(element);
+    if (element._madePositioned) {
+      element._madePositioned = undefined;
+      element.style.position =
+        element.style.top =
+        element.style.left =
+        element.style.bottom =
+        element.style.right = '';
+    }
+    return element;
+  },
+
+  makeClipping: function(element) {
+    element = $(element);
+    if (element._overflow) return element;
+    element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+    if (element._overflow !== 'hidden')
+      element.style.overflow = 'hidden';
+    return element;
+  },
+
+  undoClipping: function(element) {
+    element = $(element);
+    if (!element._overflow) return element;
+    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+    element._overflow = null;
+    return element;
+  },
+
+  cumulativeOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      element = element.offsetParent;
+    } while (element);
+    return Element._returnOffset(valueL, valueT);
+  },
+
+  positionedOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      element = element.offsetParent;
+      if (element) {
+        if (element.tagName.toUpperCase() == 'BODY') break;
+        var p = Element.getStyle(element, 'position');
+        if (p !== 'static') break;
+      }
+    } while (element);
+    return Element._returnOffset(valueL, valueT);
+  },
+
+  absolutize: function(element) {
+    element = $(element);
+    if (element.getStyle('position') == 'absolute') return element;
+    // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+    var offsets = element.positionedOffset();
+    var top     = offsets[1];
+    var left    = offsets[0];
+    var width   = element.clientWidth;
+    var height  = element.clientHeight;
+
+    element._originalLeft   = left - parseFloat(element.style.left  || 0);
+    element._originalTop    = top  - parseFloat(element.style.top || 0);
+    element._originalWidth  = element.style.width;
+    element._originalHeight = element.style.height;
+
+    element.style.position = 'absolute';
+    element.style.top    = top + 'px';
+    element.style.left   = left + 'px';
+    element.style.width  = width + 'px';
+    element.style.height = height + 'px';
+    return element;
+  },
+
+  relativize: function(element) {
+    element = $(element);
+    if (element.getStyle('position') == 'relative') return element;
+    // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+    element.style.position = 'relative';
+    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
+    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+    element.style.top    = top + 'px';
+    element.style.left   = left + 'px';
+    element.style.height = element._originalHeight;
+    element.style.width  = element._originalWidth;
+    return element;
+  },
+
+  cumulativeScrollOffset: function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.scrollTop  || 0;
+      valueL += element.scrollLeft || 0;
+      element = element.parentNode;
+    } while (element);
+    return Element._returnOffset(valueL, valueT);
+  },
+
+  getOffsetParent: function(element) {
+    if (element.offsetParent) return $(element.offsetParent);
+    if (element == document.body) return $(element);
+
+    while ((element = element.parentNode) && element != document.body)
+      if (Element.getStyle(element, 'position') != 'static')
+        return $(element);
+
+    return $(document.body);
+  },
+
+  viewportOffset: function(forElement) {
+    var valueT = 0, valueL = 0;
+
+    var element = forElement;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+
+      // Safari fix
+      if (element.offsetParent == document.body &&
+        Element.getStyle(element, 'position') == 'absolute') break;
+
+    } while (element = element.offsetParent);
+
+    element = forElement;
+    do {
+      if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) {
+        valueT -= element.scrollTop  || 0;
+        valueL -= element.scrollLeft || 0;
+      }
+    } while (element = element.parentNode);
+
+    return Element._returnOffset(valueL, valueT);
+  },
+
+  clonePosition: function(element, source) {
+    var options = Object.extend({
+      setLeft:    true,
+      setTop:     true,
+      setWidth:   true,
+      setHeight:  true,
+      offsetTop:  0,
+      offsetLeft: 0
+    }, arguments[2] || { });
+
+    // find page position of source
+    source = $(source);
+    var p = source.viewportOffset();
+
+    // find coordinate system to use
+    element = $(element);
+    var delta = [0, 0];
+    var parent = null;
+    // delta [0,0] will do fine with position: fixed elements,
+    // position:absolute needs offsetParent deltas
+    if (Element.getStyle(element, 'position') == 'absolute') {
+      parent = element.getOffsetParent();
+      delta = parent.viewportOffset();
+    }
+
+    // correct by body offsets (fixes Safari)
+    if (parent == document.body) {
+      delta[0] -= document.body.offsetLeft;
+      delta[1] -= document.body.offsetTop;
+    }
+
+    // set position
+    if (options.setLeft)   element.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
+    if (options.setTop)    element.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
+    if (options.setWidth)  element.style.width = source.offsetWidth + 'px';
+    if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+    return element;
+  }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+  getElementsBySelector: Element.Methods.select,
+  childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+  write: {
+    names: {
+      className: 'class',
+      htmlFor:   'for'
+    },
+    values: { }
+  }
+};
+
+if (Prototype.Browser.Opera) {
+  Element.Methods.getStyle = Element.Methods.getStyle.wrap(
+    function(proceed, element, style) {
+      switch (style) {
+        case 'left': case 'top': case 'right': case 'bottom':
+          if (proceed(element, 'position') === 'static') return null;
+        case 'height': case 'width':
+          // returns '0px' for hidden elements; we want it to return null
+          if (!Element.visible(element)) return null;
+
+          // returns the border-box dimensions rather than the content-box
+          // dimensions, so we subtract padding and borders from the value
+          var dim = parseInt(proceed(element, style), 10);
+
+          if (dim !== element['offset' + style.capitalize()])
+            return dim + 'px';
+
+          var properties;
+          if (style === 'height') {
+            properties = ['border-top-width', 'padding-top',
+             'padding-bottom', 'border-bottom-width'];
+          }
+          else {
+            properties = ['border-left-width', 'padding-left',
+             'padding-right', 'border-right-width'];
+          }
+          return properties.inject(dim, function(memo, property) {
+            var val = proceed(element, property);
+            return val === null ? memo : memo - parseInt(val, 10);
+          }) + 'px';
+        default: return proceed(element, style);
+      }
+    }
+  );
+
+  Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
+    function(proceed, element, attribute) {
+      if (attribute === 'title') return element.title;
+      return proceed(element, attribute);
+    }
+  );
+}
+
+else if (Prototype.Browser.IE) {
+  // IE doesn't report offsets correctly for static elements, so we change them
+  // to "relative" to get the values, then change them back.
+  Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+    function(proceed, element) {
+      element = $(element);
+      // IE throws an error if element is not in document
+      try { element.offsetParent }
+      catch(e) { return $(document.body) }
+      var position = element.getStyle('position');
+      if (position !== 'static') return proceed(element);
+      element.setStyle({ position: 'relative' });
+      var value = proceed(element);
+      element.setStyle({ position: position });
+      return value;
+    }
+  );
+
+  $w('positionedOffset viewportOffset').each(function(method) {
+    Element.Methods[method] = Element.Methods[method].wrap(
+      function(proceed, element) {
+        element = $(element);
+        try { element.offsetParent }
+        catch(e) { return Element._returnOffset(0,0) }
+        var position = element.getStyle('position');
+        if (position !== 'static') return proceed(element);
+        // Trigger hasLayout on the offset parent so that IE6 reports
+        // accurate offsetTop and offsetLeft values for position: fixed.
+        var offsetParent = element.getOffsetParent();
+        if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+          offsetParent.setStyle({ zoom: 1 });
+        element.setStyle({ position: 'relative' });
+        var value = proceed(element);
+        element.setStyle({ position: position });
+        return value;
+      }
+    );
+  });
+
+  Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap(
+    function(proceed, element) {
+      try { element.offsetParent }
+      catch(e) { return Element._returnOffset(0,0) }
+      return proceed(element);
+    }
+  );
+
+  Element.Methods.getStyle = function(element, style) {
+    element = $(element);
+    style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+    var value = element.style[style];
+    if (!value && element.currentStyle) value = element.currentStyle[style];
+
+    if (style == 'opacity') {
+      if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+        if (value[1]) return parseFloat(value[1]) / 100;
+      return 1.0;
+    }
+
+    if (value == 'auto') {
+      if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+        return element['offset' + style.capitalize()] + 'px';
+      return null;
+    }
+    return value;
+  };
+
+  Element.Methods.setOpacity = function(element, value) {
+    function stripAlpha(filter){
+      return filter.replace(/alpha\([^\)]*\)/gi,'');
+    }
+    element = $(element);
+    var currentStyle = element.currentStyle;
+    if ((currentStyle && !currentStyle.hasLayout) ||
+      (!currentStyle && element.style.zoom == 'normal'))
+        element.style.zoom = 1;
+
+    var filter = element.getStyle('filter'), style = element.style;
+    if (value == 1 || value === '') {
+      (filter = stripAlpha(filter)) ?
+        style.filter = filter : style.removeAttribute('filter');
+      return element;
+    } else if (value < 0.00001) value = 0;
+    style.filter = stripAlpha(filter) +
+      'alpha(opacity=' + (value * 100) + ')';
+    return element;
+  };
+
+  Element._attributeTranslations = {
+    read: {
+      names: {
+        'class': 'className',
+        'for':   'htmlFor'
+      },
+      values: {
+        _getAttr: function(element, attribute) {
+          return element.getAttribute(attribute, 2);
+        },
+        _getAttrNode: function(element, attribute) {
+          var node = element.getAttributeNode(attribute);
+          return node ? node.value : "";
+        },
+        _getEv: function(element, attribute) {
+          attribute = element.getAttribute(attribute);
+          return attribute ? attribute.toString().slice(23, -2) : null;
+        },
+        _flag: function(element, attribute) {
+          return $(element).hasAttribute(attribute) ? attribute : null;
+        },
+        style: function(element) {
+          return element.style.cssText.toLowerCase();
+        },
+        title: function(element) {
+          return element.title;
+        }
+      }
+    }
+  };
+
+  Element._attributeTranslations.write = {
+    names: Object.extend({
+      cellpadding: 'cellPadding',
+      cellspacing: 'cellSpacing'
+    }, Element._attributeTranslations.read.names),
+    values: {
+      checked: function(element, value) {
+        element.checked = !!value;
+      },
+
+      style: function(element, value) {
+        element.style.cssText = value ? value : '';
+      }
+    }
+  };
+
+  Element._attributeTranslations.has = {};
+
+  $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+      'encType maxLength readOnly longDesc frameBorder').each(function(attr) {
+    Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+    Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+  });
+
+  (function(v) {
+    Object.extend(v, {
+      href:        v._getAttr,
+      src:         v._getAttr,
+      type:        v._getAttr,
+      action:      v._getAttrNode,
+      disabled:    v._flag,
+      checked:     v._flag,
+      readonly:    v._flag,
+      multiple:    v._flag,
+      onload:      v._getEv,
+      onunload:    v._getEv,
+      onclick:     v._getEv,
+      ondblclick:  v._getEv,
+      onmousedown: v._getEv,
+      onmouseup:   v._getEv,
+      onmouseover: v._getEv,
+      onmousemove: v._getEv,
+      onmouseout:  v._getEv,
+      onfocus:     v._getEv,
+      onblur:      v._getEv,
+      onkeypress:  v._getEv,
+      onkeydown:   v._getEv,
+      onkeyup:     v._getEv,
+      onsubmit:    v._getEv,
+      onreset:     v._getEv,
+      onselect:    v._getEv,
+      onchange:    v._getEv
+    });
+  })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+  Element.Methods.setOpacity = function(element, value) {
+    element = $(element);
+    element.style.opacity = (value == 1) ? 0.999999 :
+      (value === '') ? '' : (value < 0.00001) ? 0 : value;
+    return element;
+  };
+}
+
+else if (Prototype.Browser.WebKit) {
+  Element.Methods.setOpacity = function(element, value) {
+    element = $(element);
+    element.style.opacity = (value == 1 || value === '') ? '' :
+      (value < 0.00001) ? 0 : value;
+
+    if (value == 1)
+      if(element.tagName.toUpperCase() == 'IMG' && element.width) {
+        element.width++; element.width--;
+      } else try {
+        var n = document.createTextNode(' ');
+        element.appendChild(n);
+        element.removeChild(n);
+      } catch (e) { }
+
+    return element;
+  };
+
+  // Safari returns margins on body which is incorrect if the child is absolutely
+  // positioned.  For performance reasons, redefine Element#cumulativeOffset for
+  // KHTML/WebKit only.
+  Element.Methods.cumulativeOffset = function(element) {
+    var valueT = 0, valueL = 0;
+    do {
+      valueT += element.offsetTop  || 0;
+      valueL += element.offsetLeft || 0;
+      if (element.offsetParent == document.body)
+        if (Element.getStyle(element, 'position') == 'absolute') break;
+
+      element = element.offsetParent;
+    } while (element);
+
+    return Element._returnOffset(valueL, valueT);
+  };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+  // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+  Element.Methods.update = function(element, content) {
+    element = $(element);
+
+    if (content && content.toElement) content = content.toElement();
+    if (Object.isElement(content)) return element.update().insert(content);
+
+    content = Object.toHTML(content);
+    var tagName = element.tagName.toUpperCase();
+
+    if (tagName in Element._insertionTranslations.tags) {
+      $A(element.childNodes).each(function(node) { element.removeChild(node) });
+      Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+        .each(function(node) { element.appendChild(node) });
+    }
+    else element.innerHTML = content.stripScripts();
+
+    content.evalScripts.bind(content).defer();
+    return element;
+  };
+}
+
+if ('outerHTML' in document.createElement('div')) {
+  Element.Methods.replace = function(element, content) {
+    element = $(element);
+
+    if (content && content.toElement) content = content.toElement();
+    if (Object.isElement(content)) {
+      element.parentNode.replaceChild(content, element);
+      return element;
+    }
+
+    content = Object.toHTML(content);
+    var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+    if (Element._insertionTranslations.tags[tagName]) {
+      var nextSibling = element.next();
+      var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+      parent.removeChild(element);
+      if (nextSibling)
+        fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+      else
+        fragments.each(function(node) { parent.appendChild(node) });
+    }
+    else element.outerHTML = content.stripScripts();
+
+    content.evalScripts.bind(content).defer();
+    return element;
+  };
+}
+
+Element._returnOffset = function(l, t) {
+  var result = [l, t];
+  result.left = l;
+  result.top = t;
+  return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+  var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+  if (t) {
+    div.innerHTML = t[0] + html + t[1];
+    t[2].times(function() { div = div.firstChild });
+  } else div.innerHTML = html;
+  return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+  before: function(element, node) {
+    element.parentNode.insertBefore(node, element);
+  },
+  top: function(element, node) {
+    element.insertBefore(node, element.firstChild);
+  },
+  bottom: function(element, node) {
+    element.appendChild(node);
+  },
+  after: function(element, node) {
+    element.parentNode.insertBefore(node, element.nextSibling);
+  },
+  tags: {
+    TABLE:  ['<table>',                '</table>',                   1],
+    TBODY:  ['<table><tbody>',         '</tbody></table>',           2],
+    TR:     ['<table><tbody><tr>',     '</tr></tbody></table>',      3],
+    TD:     ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+    SELECT: ['<select>',               '</select>',                  1]
+  }
+};
+
+(function() {
+  Object.extend(this.tags, {
+    THEAD: this.tags.TBODY,
+    TFOOT: this.tags.TBODY,
+    TH:    this.tags.TD
+  });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+  hasAttribute: function(element, attribute) {
+    attribute = Element._attributeTranslations.has[attribute] || attribute;
+    var node = $(element).getAttributeNode(attribute);
+    return !!(node && node.specified);
+  }
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+    document.createElement('div')['__proto__']) {
+  window.HTMLElement = { };
+  window.HTMLElement.prototype = document.createElement('div')['__proto__'];
+  Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.extend = (function() {
+  if (Prototype.BrowserFeatures.SpecificElementExtensions)
+    return Prototype.K;
+
+  var Methods = { }, ByTag = Element.Methods.ByTag;
+
+  var extend = Object.extend(function(element) {
+    if (!element || element._extendedByPrototype ||
+        element.nodeType != 1 || element == window) return element;
+
+    var methods = Object.clone(Methods),
+      tagName = element.tagName.toUpperCase(), property, value;
+
+    // extend methods for specific tags
+    if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+    for (property in methods) {
+      value = methods[property];
+      if (Object.isFunction(value) && !(property in element))
+        element[property] = value.methodize();
+    }
+
+    element._extendedByPrototype = Prototype.emptyFunction;
+    return element;
+
+  }, {
+    refresh: function() {
+      // extend methods for all tags (Safari doesn't need this)
+      if (!Prototype.BrowserFeatures.ElementExtensions) {
+        Object.extend(Methods, Element.Methods);
+        Object.extend(Methods, Element.Methods.Simulated);
+      }
+    }
+  });
+
+  extend.refresh();
+  return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+  if (element.hasAttribute) return element.hasAttribute(attribute);
+  return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+  var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+  if (!methods) {
+    Object.extend(Form, Form.Methods);
+    Object.extend(Form.Element, Form.Element.Methods);
+    Object.extend(Element.Methods.ByTag, {
+      "FORM":     Object.clone(Form.Methods),
+      "INPUT":    Object.clone(Form.Element.Methods),
+      "SELECT":   Object.clone(Form.Element.Methods),
+      "TEXTAREA": Object.clone(Form.Element.Methods)
+    });
+  }
+
+  if (arguments.length == 2) {
+    var tagName = methods;
+    methods = arguments[1];
+  }
+
+  if (!tagName) Object.extend(Element.Methods, methods || { });
+  else {
+    if (Object.isArray(tagName)) tagName.each(extend);
+    else extend(tagName);
+  }
+
+  function extend(tagName) {
+    tagName = tagName.toUpperCase();
+    if (!Element.Methods.ByTag[tagName])
+      Element.Methods.ByTag[tagName] = { };
+    Object.extend(Element.Methods.ByTag[tagName], methods);
+  }
+
+  function copy(methods, destination, onlyIfAbsent) {
+    onlyIfAbsent = onlyIfAbsent || false;
+    for (var property in methods) {
+      var value = methods[property];
+      if (!Object.isFunction(value)) continue;
+      if (!onlyIfAbsent || !(property in destination))
+        destination[property] = value.methodize();
+    }
+  }
+
+  function findDOMClass(tagName) {
+    var klass;
+    var trans = {
+      "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+      "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+      "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+      "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+      "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+      "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+      "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+      "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+      "FrameSet", "IFRAME": "IFrame"
+    };
+    if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+    if (window[klass]) return window[klass];
+    klass = 'HTML' + tagName + 'Element';
+    if (window[klass]) return window[klass];
+    klass = 'HTML' + tagName.capitalize() + 'Element';
+    if (window[klass]) return window[klass];
+
+    window[klass] = { };
+    window[klass].prototype = document.createElement(tagName)['__proto__'];
+    return window[klass];
+  }
+
+  if (F.ElementExtensions) {
+    copy(Element.Methods, HTMLElement.prototype);
+    copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+  }
+
+  if (F.SpecificElementExtensions) {
+    for (var tag in Element.Methods.ByTag) {
+      var klass = findDOMClass(tag);
+      if (Object.isUndefined(klass)) continue;
+      copy(T[tag], klass.prototype);
+    }
+  }
+
+  Object.extend(Element, Element.Methods);
+  delete Element.ByTag;
+
+  if (Element.extend.refresh) Element.extend.refresh();
+  Element.cache = { };
+};
+
+document.viewport = {
+  getDimensions: function() {
+    var dimensions = { }, B = Prototype.Browser;
+    $w('width height').each(function(d) {
+      var D = d.capitalize();
+      if (B.WebKit && !document.evaluate) {
+        // Safari <3.0 needs self.innerWidth/Height
+        dimensions[d] = self['inner' + D];
+      } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) {
+        // Opera <9.5 needs document.body.clientWidth/Height
+        dimensions[d] = document.body['client' + D]
+      } else {
+        dimensions[d] = document.documentElement['client' + D];
+      }
+    });
+    return dimensions;
+  },
+
+  getWidth: function() {
+    return this.getDimensions().width;
+  },
+
+  getHeight: function() {
+    return this.getDimensions().height;
+  },
+
+  getScrollOffsets: function() {
+    return Element._returnOffset(
+      window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+      window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
+  }
+};
+/* Portions of the Selector class are derived from Jack Slocum's DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license.  Please see http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create({
+  initialize: function(expression) {
+    this.expression = expression.strip();
+
+    if (this.shouldUseSelectorsAPI()) {
+      this.mode = 'selectorsAPI';
+    } else if (this.shouldUseXPath()) {
+      this.mode = 'xpath';
+      this.compileXPathMatcher();
+    } else {
+      this.mode = "normal";
+      this.compileMatcher();
+    }
+
+  },
+
+  shouldUseXPath: function() {
+    if (!Prototype.BrowserFeatures.XPath) return false;
+
+    var e = this.expression;
+
+    // Safari 3 chokes on :*-of-type and :empty
+    if (Prototype.Browser.WebKit &&
+     (e.include("-of-type") || e.include(":empty")))
+      return false;
+
+    // XPath can't do namespaced attributes, nor can it read
+    // the "checked" property from DOM nodes
+    if ((/(\[[\w-]*?:|:checked)/).test(e))
+      return false;
+
+    return true;
+  },
+
+  shouldUseSelectorsAPI: function() {
+    if (!Prototype.BrowserFeatures.SelectorsAPI) return false;
+
+    if (!Selector._div) Selector._div = new Element('div');
+
+    // Make sure the browser treats the selector as valid. Test on an
+    // isolated element to minimize cost of this check.
+    try {
+      Selector._div.querySelector(this.expression);
+    } catch(e) {
+      return false;
+    }
+
+    return true;
+  },
+
+  compileMatcher: function() {
+    var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+        c = Selector.criteria, le, p, m;
+
+    if (Selector._cache[e]) {
+      this.matcher = Selector._cache[e];
+      return;
+    }
+
+    this.matcher = ["this.matcher = function(root) {",
+                    "var r = root, h = Selector.handlers, c = false, n;"];
+
+    while (e && le != e && (/\S/).test(e)) {
+      le = e;
+      for (var i in ps) {
+        p = ps[i];
+        if (m = e.match(p)) {
+          this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+            new Template(c[i]).evaluate(m));
+          e = e.replace(m[0], '');
+          break;
+        }
+      }
+    }
+
+    this.matcher.push("return h.unique(n);\n}");
+    eval(this.matcher.join('\n'));
+    Selector._cache[this.expression] = this.matcher;
+  },
+
+  compileXPathMatcher: function() {
+    var e = this.expression, ps = Selector.patterns,
+        x = Selector.xpath, le, m;
+
+    if (Selector._cache[e]) {
+      this.xpath = Selector._cache[e]; return;
+    }
+
+    this.matcher = ['.//*'];
+    while (e && le != e && (/\S/).test(e)) {
+      le = e;
+      for (var i in ps) {
+        if (m = e.match(ps[i])) {
+          this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+            new Template(x[i]).evaluate(m));
+          e = e.replace(m[0], '');
+          break;
+        }
+      }
+    }
+
+    this.xpath = this.matcher.join('');
+    Selector._cache[this.expression] = this.xpath;
+  },
+
+  findElements: function(root) {
+    root = root || document;
+    var e = this.expression, results;
+
+    switch (this.mode) {
+      case 'selectorsAPI':
+        // querySelectorAll queries document-wide, then filters to descendants
+        // of the context element. That's not what we want.
+        // Add an explicit context to the selector if necessary.
+        if (root !== document) {
+          var oldId = root.id, id = $(root).identify();
+          e = "#" + id + " " + e;
+        }
+
+        results = $A(root.querySelectorAll(e)).map(Element.extend);
+        root.id = oldId;
+
+        return results;
+      case 'xpath':
+        return document._getElementsByXPath(this.xpath, root);
+      default:
+       return this.matcher(root);
+    }
+  },
+
+  match: function(element) {
+    this.tokens = [];
+
+    var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+    var le, p, m;
+
+    while (e && le !== e && (/\S/).test(e)) {
+      le = e;
+      for (var i in ps) {
+        p = ps[i];
+        if (m = e.match(p)) {
+          // use the Selector.assertions methods unless the selector
+          // is too complex.
+          if (as[i]) {
+            this.tokens.push([i, Object.clone(m)]);
+            e = e.replace(m[0], '');
+          } else {
+            // reluctantly do a document-wide search
+            // and look for a match in the array
+            return this.findElements(document).include(element);
+          }
+        }
+      }
+    }
+
+    var match = true, name, matches;
+    for (var i = 0, token; token = this.tokens[i]; i++) {
+      name = token[0], matches = token[1];
+      if (!Selector.assertions[name](element, matches)) {
+        match = false; break;
+      }
+    }
+
+    return match;
+  },
+
+  toString: function() {
+    return this.expression;
+  },
+
+  inspect: function() {
+    return "#<Selector:" + this.expression.inspect() + ">";
+  }
+});
+
+Object.extend(Selector, {
+  _cache: { },
+
+  xpath: {
+    descendant:   "//*",
+    child:        "/*",
+    adjacent:     "/following-sibling::*[1]",
+    laterSibling: '/following-sibling::*',
+    tagName:      function(m) {
+      if (m[1] == '*') return '';
+      return "[local-name()='" + m[1].toLowerCase() +
+             "' or local-name()='" + m[1].toUpperCase() + "']";
+    },
+    className:    "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+    id:           "[@id='#{1}']",
+    attrPresence: function(m) {
+      m[1] = m[1].toLowerCase();
+      return new Template("[@#{1}]").evaluate(m);
+    },
+    attr: function(m) {
+      m[1] = m[1].toLowerCase();
+      m[3] = m[5] || m[6];
+      return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+    },
+    pseudo: function(m) {
+      var h = Selector.xpath.pseudos[m[1]];
+      if (!h) return '';
+      if (Object.isFunction(h)) return h(m);
+      return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+    },
+    operators: {
+      '=':  "[@#{1}='#{3}']",
+      '!=': "[@#{1}!='#{3}']",
+      '^=': "[starts-with(@#{1}, '#{3}')]",
+      '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+      '*=': "[contains(@#{1}, '#{3}')]",
+      '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+      '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+    },
+    pseudos: {
+      'first-child': '[not(preceding-sibling::*)]',
+      'last-child':  '[not(following-sibling::*)]',
+      'only-child':  '[not(preceding-sibling::* or following-sibling::*)]',
+      'empty':       "[count(*) = 0 and (count(text()) = 0)]",
+      'checked':     "[@checked]",
+      'disabled':    "[(@disabled) and (@type!='hidden')]",
+      'enabled':     "[not(@disabled) and (@type!='hidden')]",
+      'not': function(m) {
+        var e = m[6], p = Selector.patterns,
+            x = Selector.xpath, le, v;
+
+        var exclusion = [];
+        while (e && le != e && (/\S/).test(e)) {
+          le = e;
+          for (var i in p) {
+            if (m = e.match(p[i])) {
+              v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+              exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+              e = e.replace(m[0], '');
+              break;
+            }
+          }
+        }
+        return "[not(" + exclusion.join(" and ") + ")]";
+      },
+      'nth-child':      function(m) {
+        return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+      },
+      'nth-last-child': function(m) {
+        return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+      },
+      'nth-of-type':    function(m) {
+        return Selector.xpath.pseudos.nth("position() ", m);
+      },
+      'nth-last-of-type': function(m) {
+        return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+      },
+      'first-of-type':  function(m) {
+        m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+      },
+      'last-of-type':   function(m) {
+        m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+      },
+      'only-of-type':   function(m) {
+        var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+      },
+      nth: function(fragment, m) {
+        var mm, formula = m[6], predicate;
+        if (formula == 'even') formula = '2n+0';
+        if (formula == 'odd')  formula = '2n+1';
+        if (mm = formula.match(/^(\d+)$/)) // digit only
+          return '[' + fragment + "= " + mm[1] + ']';
+        if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+          if (mm[1] == "-") mm[1] = -1;
+          var a = mm[1] ? Number(mm[1]) : 1;
+          var b = mm[2] ? Number(mm[2]) : 0;
+          predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+          "((#{fragment} - #{b}) div #{a} >= 0)]";
+          return new Template(predicate).evaluate({
+            fragment: fragment, a: a, b: b });
+        }
+      }
+    }
+  },
+
+  criteria: {
+    tagName:      'n = h.tagName(n, r, "#{1}", c);      c = false;',
+    className:    'n = h.className(n, r, "#{1}", c);    c = false;',
+    id:           'n = h.id(n, r, "#{1}", c);           c = false;',
+    attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
+    attr: function(m) {
+      m[3] = (m[5] || m[6]);
+      return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
+    },
+    pseudo: function(m) {
+      if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+      return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+    },
+    descendant:   'c = "descendant";',
+    child:        'c = "child";',
+    adjacent:     'c = "adjacent";',
+    laterSibling: 'c = "laterSibling";'
+  },
+
+  patterns: {
+    // combinators must be listed first
+    // (and descendant needs to be last combinator)
+    laterSibling: /^\s*~\s*/,
+    child:        /^\s*>\s*/,
+    adjacent:     /^\s*\+\s*/,
+    descendant:   /^\s/,
+
+    // selectors follow
+    tagName:      /^\s*(\*|[\w\-]+)(\b|$)?/,
+    id:           /^#([\w\-\*]+)(\b|$)/,
+    className:    /^\.([\w\-\*]+)(\b|$)/,
+    pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
+    attrPresence: /^\[((?:[\w]+:)?[\w]+)\]/,
+    attr:         /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+  },
+
+  // for Selector.match and Element#match
+  assertions: {
+    tagName: function(element, matches) {
+      return matches[1].toUpperCase() == element.tagName.toUpperCase();
+    },
+
+    className: function(element, matches) {
+      return Element.hasClassName(element, matches[1]);
+    },
+
+    id: function(element, matches) {
+      return element.id === matches[1];
+    },
+
+    attrPresence: function(element, matches) {
+      return Element.hasAttribute(element, matches[1]);
+    },
+
+    attr: function(element, matches) {
+      var nodeValue = Element.readAttribute(element, matches[1]);
+      return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
+    }
+  },
+
+  handlers: {
+    // UTILITY FUNCTIONS
+    // joins two collections
+    concat: function(a, b) {
+      for (var i = 0, node; node = b[i]; i++)
+        a.push(node);
+      return a;
+    },
+
+    // marks an array of nodes for counting
+    mark: function(nodes) {
+      var _true = Prototype.emptyFunction;
+      for (var i = 0, node; node = nodes[i]; i++)
+        node._countedByPrototype = _true;
+      return nodes;
+    },
+
+    unmark: function(nodes) {
+      for (var i = 0, node; node = nodes[i]; i++)
+        node._countedByPrototype = undefined;
+      return nodes;
+    },
+
+    // mark each child node with its position (for nth calls)
+    // "ofType" flag indicates whether we're indexing for nth-of-type
+    // rather than nth-child
+    index: function(parentNode, reverse, ofType) {
+      parentNode._countedByPrototype = Prototype.emptyFunction;
+      if (reverse) {
+        for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+          var node = nodes[i];
+          if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+        }
+      } else {
+        for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+          if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
+      }
+    },
+
+    // filters out duplicates and extends all nodes
+    unique: function(nodes) {
+      if (nodes.length == 0) return nodes;
+      var results = [], n;
+      for (var i = 0, l = nodes.length; i < l; i++)
+        if (!(n = nodes[i])._countedByPrototype) {
+          n._countedByPrototype = Prototype.emptyFunction;
+          results.push(Element.extend(n));
+        }
+      return Selector.handlers.unmark(results);
+    },
+
+    // COMBINATOR FUNCTIONS
+    descendant: function(nodes) {
+      var h = Selector.handlers;
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        h.concat(results, node.getElementsByTagName('*'));
+      return results;
+    },
+
+    child: function(nodes) {
+      var h = Selector.handlers;
+      for (var i = 0, results = [], node; node = nodes[i]; i++) {
+        for (var j = 0, child; child = node.childNodes[j]; j++)
+          if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+      }
+      return results;
+    },
+
+    adjacent: function(nodes) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++) {
+        var next = this.nextElementSibling(node);
+        if (next) results.push(next);
+      }
+      return results;
+    },
+
+    laterSibling: function(nodes) {
+      var h = Selector.handlers;
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        h.concat(results, Element.nextSiblings(node));
+      return results;
+    },
+
+    nextElementSibling: function(node) {
+      while (node = node.nextSibling)
+        if (node.nodeType == 1) return node;
+      return null;
+    },
+
+    previousElementSibling: function(node) {
+      while (node = node.previousSibling)
+        if (node.nodeType == 1) return node;
+      return null;
+    },
+
+    // TOKEN FUNCTIONS
+    tagName: function(nodes, root, tagName, combinator) {
+      var uTagName = tagName.toUpperCase();
+      var results = [], h = Selector.handlers;
+      if (nodes) {
+        if (combinator) {
+          // fastlane for ordinary descendant combinators
+          if (combinator == "descendant") {
+            for (var i = 0, node; node = nodes[i]; i++)
+              h.concat(results, node.getElementsByTagName(tagName));
+            return results;
+          } else nodes = this[combinator](nodes);
+          if (tagName == "*") return nodes;
+        }
+        for (var i = 0, node; node = nodes[i]; i++)
+          if (node.tagName.toUpperCase() === uTagName) results.push(node);
+        return results;
+      } else return root.getElementsByTagName(tagName);
+    },
+
+    id: function(nodes, root, id, combinator) {
+      var targetNode = $(id), h = Selector.handlers;
+      if (!targetNode) return [];
+      if (!nodes && root == document) return [targetNode];
+      if (nodes) {
+        if (combinator) {
+          if (combinator == 'child') {
+            for (var i = 0, node; node = nodes[i]; i++)
+              if (targetNode.parentNode == node) return [targetNode];
+          } else if (combinator == 'descendant') {
+            for (var i = 0, node; node = nodes[i]; i++)
+              if (Element.descendantOf(targetNode, node)) return [targetNode];
+          } else if (combinator == 'adjacent') {
+            for (var i = 0, node; node = nodes[i]; i++)
+              if (Selector.handlers.previousElementSibling(targetNode) == node)
+                return [targetNode];
+          } else nodes = h[combinator](nodes);
+        }
+        for (var i = 0, node; node = nodes[i]; i++)
+          if (node == targetNode) return [targetNode];
+        return [];
+      }
+      return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+    },
+
+    className: function(nodes, root, className, combinator) {
+      if (nodes && combinator) nodes = this[combinator](nodes);
+      return Selector.handlers.byClassName(nodes, root, className);
+    },
+
+    byClassName: function(nodes, root, className) {
+      if (!nodes) nodes = Selector.handlers.descendant([root]);
+      var needle = ' ' + className + ' ';
+      for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+        nodeClassName = node.className;
+        if (nodeClassName.length == 0) continue;
+        if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+          results.push(node);
+      }
+      return results;
+    },
+
+    attrPresence: function(nodes, root, attr, combinator) {
+      if (!nodes) nodes = root.getElementsByTagName("*");
+      if (nodes && combinator) nodes = this[combinator](nodes);
+      var results = [];
+      for (var i = 0, node; node = nodes[i]; i++)
+        if (Element.hasAttribute(node, attr)) results.push(node);
+      return results;
+    },
+
+    attr: function(nodes, root, attr, value, operator, combinator) {
+      if (!nodes) nodes = root.getElementsByTagName("*");
+      if (nodes && combinator) nodes = this[combinator](nodes);
+      var handler = Selector.operators[operator], results = [];
+      for (var i = 0, node; node = nodes[i]; i++) {
+        var nodeValue = Element.readAttribute(node, attr);
+        if (nodeValue === null) continue;
+        if (handler(nodeValue, value)) results.push(node);
+      }
+      return results;
+    },
+
+    pseudo: function(nodes, name, value, root, combinator) {
+      if (nodes && combinator) nodes = this[combinator](nodes);
+      if (!nodes) nodes = root.getElementsByTagName("*");
+      return Selector.pseudos[name](nodes, value, root);
+    }
+  },
+
+  pseudos: {
+    'first-child': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++) {
+        if (Selector.handlers.previousElementSibling(node)) continue;
+          results.push(node);
+      }
+      return results;
+    },
+    'last-child': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++) {
+        if (Selector.handlers.nextElementSibling(node)) continue;
+          results.push(node);
+      }
+      return results;
+    },
+    'only-child': function(nodes, value, root) {
+      var h = Selector.handlers;
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+          results.push(node);
+      return results;
+    },
+    'nth-child':        function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, formula, root);
+    },
+    'nth-last-child':   function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, formula, root, true);
+    },
+    'nth-of-type':      function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, formula, root, false, true);
+    },
+    'nth-last-of-type': function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, formula, root, true, true);
+    },
+    'first-of-type':    function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, "1", root, false, true);
+    },
+    'last-of-type':     function(nodes, formula, root) {
+      return Selector.pseudos.nth(nodes, "1", root, true, true);
+    },
+    'only-of-type':     function(nodes, formula, root) {
+      var p = Selector.pseudos;
+      return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+    },
+
+    // handles the an+b logic
+    getIndices: function(a, b, total) {
+      if (a == 0) return b > 0 ? [b] : [];
+      return $R(1, total).inject([], function(memo, i) {
+        if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+        return memo;
+      });
+    },
+
+    // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+    nth: function(nodes, formula, root, reverse, ofType) {
+      if (nodes.length == 0) return [];
+      if (formula == 'even') formula = '2n+0';
+      if (formula == 'odd')  formula = '2n+1';
+      var h = Selector.handlers, results = [], indexed = [], m;
+      h.mark(nodes);
+      for (var i = 0, node; node = nodes[i]; i++) {
+        if (!node.parentNode._countedByPrototype) {
+          h.index(node.parentNode, reverse, ofType);
+          indexed.push(node.parentNode);
+        }
+      }
+      if (formula.match(/^\d+$/)) { // just a number
+        formula = Number(formula);
+        for (var i = 0, node; node = nodes[i]; i++)
+          if (node.nodeIndex == formula) results.push(node);
+      } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+        if (m[1] == "-") m[1] = -1;
+        var a = m[1] ? Number(m[1]) : 1;
+        var b = m[2] ? Number(m[2]) : 0;
+        var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+        for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+          for (var j = 0; j < l; j++)
+            if (node.nodeIndex == indices[j]) results.push(node);
+        }
+      }
+      h.unmark(nodes);
+      h.unmark(indexed);
+      return results;
+    },
+
+    'empty': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++) {
+        // IE treats comments as element nodes
+        if (node.tagName == '!' || node.firstChild) continue;
+        results.push(node);
+      }
+      return results;
+    },
+
+    'not': function(nodes, selector, root) {
+      var h = Selector.handlers, selectorType, m;
+      var exclusions = new Selector(selector).findElements(root);
+      h.mark(exclusions);
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        if (!node._countedByPrototype) results.push(node);
+      h.unmark(exclusions);
+      return results;
+    },
+
+    'enabled': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        if (!node.disabled && (!node.type || node.type !== 'hidden'))
+          results.push(node);
+      return results;
+    },
+
+    'disabled': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        if (node.disabled) results.push(node);
+      return results;
+    },
+
+    'checked': function(nodes, value, root) {
+      for (var i = 0, results = [], node; node = nodes[i]; i++)
+        if (node.checked) results.push(node);
+      return results;
+    }
+  },
+
+  operators: {
+    '=':  function(nv, v) { return nv == v; },
+    '!=': function(nv, v) { return nv != v; },
+    '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); },
+    '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); },
+    '*=': function(nv, v) { return nv == v || nv && nv.include(v); },
+    '$=': function(nv, v) { return nv.endsWith(v); },
+    '*=': function(nv, v) { return nv.include(v); },
+    '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+    '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() +
+     '-').include('-' + (v || "").toUpperCase() + '-'); }
+  },
+
+  split: function(expression) {
+    var expressions = [];
+    expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+      expressions.push(m[1].strip());
+    });
+    return expressions;
+  },
+
+  matchElements: function(elements, expression) {
+    var matches = $$(expression), h = Selector.handlers;
+    h.mark(matches);
+    for (var i = 0, results = [], element; element = elements[i]; i++)
+      if (element._countedByPrototype) results.push(element);
+    h.unmark(matches);
+    return results;
+  },
+
+  findElement: function(elements, expression, index) {
+    if (Object.isNumber(expression)) {
+      index = expression; expression = false;
+    }
+    return Selector.matchElements(elements, expression || '*')[index || 0];
+  },
+
+  findChildElements: function(element, expressions) {
+    expressions = Selector.split(expressions.join(','));
+    var results = [], h = Selector.handlers;
+    for (var i = 0, l = expressions.length, selector; i < l; i++) {
+      selector = new Selector(expressions[i].strip());
+      h.concat(results, selector.findElements(element));
+    }
+    return (l > 1) ? h.unique(results) : results;
+  }
+});
+
+if (Prototype.Browser.IE) {
+  Object.extend(Selector.handlers, {
+    // IE returns comment nodes on getElementsByTagName("*").
+    // Filter them out.
+    concat: function(a, b) {
+      for (var i = 0, node; node = b[i]; i++)
+        if (node.tagName !== "!") a.push(node);
+      return a;
+    },
+
+    // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+    unmark: function(nodes) {
+      for (var i = 0, node; node = nodes[i]; i++)
+        node.removeAttribute('_countedByPrototype');
+      return nodes;
+    }
+  });
+}
+
+function $$() {
+  return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+  reset: function(form) {
+    $(form).reset();
+    return form;
+  },
+
+  serializeElements: function(elements, options) {
+    if (typeof options != 'object') options = { hash: !!options };
+    else if (Object.isUndefined(options.hash)) options.hash = true;
+    var key, value, submitted = false, submit = options.submit;
+
+    var data = elements.inject({ }, function(result, element) {
+      if (!element.disabled && element.name) {
+        key = element.name; value = $(element).getValue();
+        if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
+            submit !== false && (!submit || key == submit) && (submitted = true)))) {
+          if (key in result) {
+            // a key is already present; construct an array of values
+            if (!Object.isArray(result[key])) result[key] = [result[key]];
+            result[key].push(value);
+          }
+          else result[key] = value;
+        }
+      }
+      return result;
+    });
+
+    return options.hash ? data : Object.toQueryString(data);
+  }
+};
+
+Form.Methods = {
+  serialize: function(form, options) {
+    return Form.serializeElements(Form.getElements(form), options);
+  },
+
+  getElements: function(form) {
+    return $A($(form).getElementsByTagName('*')).inject([],
+      function(elements, child) {
+        if (Form.Element.Serializers[child.tagName.toLowerCase()])
+          elements.push(Element.extend(child));
+        return elements;
+      }
+    );
+  },
+
+  getInputs: function(form, typeName, name) {
+    form = $(form);
+    var inputs = form.getElementsByTagName('input');
+
+    if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+      var input = inputs[i];
+      if ((typeName && input.type != typeName) || (name && input.name != name))
+        continue;
+      matchingInputs.push(Element.extend(input));
+    }
+
+    return matchingInputs;
+  },
+
+  disable: function(form) {
+    form = $(form);
+    Form.getElements(form).invoke('disable');
+    return form;
+  },
+
+  enable: function(form) {
+    form = $(form);
+    Form.getElements(form).invoke('enable');
+    return form;
+  },
+
+  findFirstElement: function(form) {
+    var elements = $(form).getElements().findAll(function(element) {
+      return 'hidden' != element.type && !element.disabled;
+    });
+    var firstByIndex = elements.findAll(function(element) {
+      return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+    }).sortBy(function(element) { return element.tabIndex }).first();
+
+    return firstByIndex ? firstByIndex : elements.find(function(element) {
+      return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+    });
+  },
+
+  focusFirstElement: function(form) {
+    form = $(form);
+    form.findFirstElement().activate();
+    return form;
+  },
+
+  request: function(form, options) {
+    form = $(form), options = Object.clone(options || { });
+
+    var params = options.parameters, action = form.readAttribute('action') || '';
+    if (action.blank()) action = window.location.href;
+    options.parameters = form.serialize(true);
+
+    if (params) {
+      if (Object.isString(params)) params = params.toQueryParams();
+      Object.extend(options.parameters, params);
+    }
+
+    if (form.hasAttribute('method') && !options.method)
+      options.method = form.method;
+
+    return new Ajax.Request(action, options);
+  }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+  focus: function(element) {
+    $(element).focus();
+    return element;
+  },
+
+  select: function(element) {
+    $(element).select();
+    return element;
+  }
+};
+
+Form.Element.Methods = {
+  serialize: function(element) {
+    element = $(element);
+    if (!element.disabled && element.name) {
+      var value = element.getValue();
+      if (value != undefined) {
+        var pair = { };
+        pair[element.name] = value;
+        return Object.toQueryString(pair);
+      }
+    }
+    return '';
+  },
+
+  getValue: function(element) {
+    element = $(element);
+    var method = element.tagName.toLowerCase();
+    return Form.Element.Serializers[method](element);
+  },
+
+  setValue: function(element, value) {
+    element = $(element);
+    var method = element.tagName.toLowerCase();
+    Form.Element.Serializers[method](element, value);
+    return element;
+  },
+
+  clear: function(element) {
+    $(element).value = '';
+    return element;
+  },
+
+  present: function(element) {
+    return $(element).value != '';
+  },
+
+  activate: function(element) {
+    element = $(element);
+    try {
+      element.focus();
+      if (element.select && (element.tagName.toLowerCase() != 'input' ||
+          !['button', 'reset', 'submit'].include(element.type)))
+        element.select();
+    } catch (e) { }
+    return element;
+  },
+
+  disable: function(element) {
+    element = $(element);
+    element.disabled = true;
+    return element;
+  },
+
+  enable: function(element) {
+    element = $(element);
+    element.disabled = false;
+    return element;
+  }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+  input: function(element, value) {
+    switch (element.type.toLowerCase()) {
+      case 'checkbox':
+      case 'radio':
+        return Form.Element.Serializers.inputSelector(element, value);
+      default:
+        return Form.Element.Serializers.textarea(element, value);
+    }
+  },
+
+  inputSelector: function(element, value) {
+    if (Object.isUndefined(value)) return element.checked ? element.value : null;
+    else element.checked = !!value;
+  },
+
+  textarea: function(element, value) {
+    if (Object.isUndefined(value)) return element.value;
+    else element.value = value;
+  },
+
+  select: function(element, value) {
+    if (Object.isUndefined(value))
+      return this[element.type == 'select-one' ?
+        'selectOne' : 'selectMany'](element);
+    else {
+      var opt, currentValue, single = !Object.isArray(value);
+      for (var i = 0, length = element.length; i < length; i++) {
+        opt = element.options[i];
+        currentValue = this.optionValue(opt);
+        if (single) {
+          if (currentValue == value) {
+            opt.selected = true;
+            return;
+          }
+        }
+        else opt.selected = value.include(currentValue);
+      }
+    }
+  },
+
+  selectOne: function(element) {
+    var index = element.selectedIndex;
+    return index >= 0 ? this.optionValue(element.options[index]) : null;
+  },
+
+  selectMany: function(element) {
+    var values, length = element.length;
+    if (!length) return null;
+
+    for (var i = 0, values = []; i < length; i++) {
+      var opt = element.options[i];
+      if (opt.selected) values.push(this.optionValue(opt));
+    }
+    return values;
+  },
+
+  optionValue: function(opt) {
+    // extend element because hasAttribute may not be native
+    return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+  }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+  initialize: function($super, element, frequency, callback) {
+    $super(callback, frequency);
+    this.element   = $(element);
+    this.lastValue = this.getValue();
+  },
+
+  execute: function() {
+    var value = this.getValue();
+    if (Object.isString(this.lastValue) && Object.isString(value) ?
+        this.lastValue != value : String(this.lastValue) != String(value)) {
+      this.callback(this.element, value);
+      this.lastValue = value;
+    }
+  }
+});
+
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+  initialize: function(element, callback) {
+    this.element  = $(element);
+    this.callback = callback;
+
+    this.lastValue = this.getValue();
+    if (this.element.tagName.toLowerCase() == 'form')
+      this.registerFormCallbacks();
+    else
+      this.registerCallback(this.element);
+  },
+
+  onElementEvent: function() {
+    var value = this.getValue();
+    if (this.lastValue != value) {
+      this.callback(this.element, value);
+      this.lastValue = value;
+    }
+  },
+
+  registerFormCallbacks: function() {
+    Form.getElements(this.element).each(this.registerCallback, this);
+  },
+
+  registerCallback: function(element) {
+    if (element.type) {
+      switch (element.type.toLowerCase()) {
+        case 'checkbox':
+        case 'radio':
+          Event.observe(element, 'click', this.onElementEvent.bind(this));
+          break;
+        default:
+          Event.observe(element, 'change', this.onElementEvent.bind(this));
+          break;
+      }
+    }
+  }
+});
+
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+  getValue: function() {
+    return Form.serialize(this.element);
+  }
+});
+if (!window.Event) var Event = { };
+
+Object.extend(Event, {
+  KEY_BACKSPACE: 8,
+  KEY_TAB:       9,
+  KEY_RETURN:   13,
+  KEY_ESC:      27,
+  KEY_LEFT:     37,
+  KEY_UP:       38,
+  KEY_RIGHT:    39,
+  KEY_DOWN:     40,
+  KEY_DELETE:   46,
+  KEY_HOME:     36,
+  KEY_END:      35,
+  KEY_PAGEUP:   33,
+  KEY_PAGEDOWN: 34,
+  KEY_INSERT:   45,
+
+  cache: { },
+
+  relatedTarget: function(event) {
+    var element;
+    switch(event.type) {
+      case 'mouseover': element = event.fromElement; break;
+      case 'mouseout':  element = event.toElement;   break;
+      default: return null;
+    }
+    return Element.extend(element);
+  }
+});
+
+Event.Methods = (function() {
+  var isButton;
+
+  if (Prototype.Browser.IE) {
+    var buttonMap = { 0: 1, 1: 4, 2: 2 };
+    isButton = function(event, code) {
+      return event.button == buttonMap[code];
+    };
+
+  } else if (Prototype.Browser.WebKit) {
+    isButton = function(event, code) {
+      switch (code) {
+        case 0: return event.which == 1 && !event.metaKey;
+        case 1: return event.which == 1 && event.metaKey;
+        default: return false;
+      }
+    };
+
+  } else {
+    isButton = function(event, code) {
+      return event.which ? (event.which === code + 1) : (event.button === code);
+    };
+  }
+
+  return {
+    isLeftClick:   function(event) { return isButton(event, 0) },
+    isMiddleClick: function(event) { return isButton(event, 1) },
+    isRightClick:  function(event) { return isButton(event, 2) },
+
+    element: function(event) {
+      event = Event.extend(event);
+
+      var node          = event.target,
+          type          = event.type,
+          currentTarget = event.currentTarget;
+
+      if (currentTarget && currentTarget.tagName) {
+        // Firefox screws up the "click" event when moving between radio buttons
+        // via arrow keys. It also screws up the "load" and "error" events on images,
+        // reporting the document as the target instead of the original image.
+        if (type === 'load' || type === 'error' ||
+          (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
+            && currentTarget.type === 'radio'))
+              node = currentTarget;
+      }
+      if (node.nodeType == Node.TEXT_NODE) node = node.parentNode;
+      return Element.extend(node);
+    },
+
+    findElement: function(event, expression) {
+      var element = Event.element(event);
+      if (!expression) return element;
+      var elements = [element].concat(element.ancestors());
+      return Selector.findElement(elements, expression, 0);
+    },
+
+    pointer: function(event) {
+      var docElement = document.documentElement,
+      body = document.body || { scrollLeft: 0, scrollTop: 0 };
+      return {
+        x: event.pageX || (event.clientX +
+          (docElement.scrollLeft || body.scrollLeft) -
+          (docElement.clientLeft || 0)),
+        y: event.pageY || (event.clientY +
+          (docElement.scrollTop || body.scrollTop) -
+          (docElement.clientTop || 0))
+      };
+    },
+
+    pointerX: function(event) { return Event.pointer(event).x },
+    pointerY: function(event) { return Event.pointer(event).y },
+
+    stop: function(event) {
+      Event.extend(event);
+      event.preventDefault();
+      event.stopPropagation();
+      event.stopped = true;
+    }
+  };
+})();
+
+Event.extend = (function() {
+  var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+    m[name] = Event.Methods[name].methodize();
+    return m;
+  });
+
+  if (Prototype.Browser.IE) {
+    Object.extend(methods, {
+      stopPropagation: function() { this.cancelBubble = true },
+      preventDefault:  function() { this.returnValue = false },
+      inspect: function() { return "[object Event]" }
+    });
+
+    return function(event) {
+      if (!event) return false;
+      if (event._extendedByPrototype) return event;
+
+      event._extendedByPrototype = Prototype.emptyFunction;
+      var pointer = Event.pointer(event);
+      Object.extend(event, {
+        target: event.srcElement,
+        relatedTarget: Event.relatedTarget(event),
+        pageX:  pointer.x,
+        pageY:  pointer.y
+      });
+      return Object.extend(event, methods);
+    };
+
+  } else {
+    Event.prototype = Event.prototype || document.createEvent("HTMLEvents")['__proto__'];
+    Object.extend(Event.prototype, methods);
+    return Prototype.K;
+  }
+})();
+
+Object.extend(Event, (function() {
+  var cache = Event.cache;
+
+  function getEventID(element) {
+    if (element._prototypeEventID) return element._prototypeEventID[0];
+    arguments.callee.id = arguments.callee.id || 1;
+    return element._prototypeEventID = [++arguments.callee.id];
+  }
+
+  function getDOMEventName(eventName) {
+    if (eventName && eventName.include(':')) return "dataavailable";
+    return eventName;
+  }
+
+  function getCacheForID(id) {
+    return cache[id] = cache[id] || { };
+  }
+
+  function getWrappersForEventName(id, eventName) {
+    var c = getCacheForID(id);
+    return c[eventName] = c[eventName] || [];
+  }
+
+  function createWrapper(element, eventName, handler) {
+    var id = getEventID(element);
+    var c = getWrappersForEventName(id, eventName);
+    if (c.pluck("handler").include(handler)) return false;
+
+    var wrapper = function(event) {
+      if (!Event || !Event.extend ||
+        (event.eventName && event.eventName != eventName))
+          return false;
+
+      Event.extend(event);
+      handler.call(element, event);
+    };
+
+    wrapper.handler = handler;
+    c.push(wrapper);
+    return wrapper;
+  }
+
+  function findWrapper(id, eventName, handler) {
+    var c = getWrappersForEventName(id, eventName);
+    return c.find(function(wrapper) { return wrapper.handler == handler });
+  }
+
+  function destroyWrapper(id, eventName, handler) {
+    var c = getCacheForID(id);
+    if (!c[eventName]) return false;
+    c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+  }
+
+  function destroyCache() {
+    for (var id in cache)
+      for (var eventName in cache[id])
+        cache[id][eventName] = null;
+  }
+
+
+  // Internet Explorer needs to remove event handlers on page unload
+  // in order to avoid memory leaks.
+  if (window.attachEvent) {
+    window.attachEvent("onunload", destroyCache);
+  }
+
+  // Safari has a dummy event handler on page unload so that it won't
+  // use its bfcache. Safari <= 3.1 has an issue with restoring the "document"
+  // object when page is returned to via the back button using its bfcache.
+  if (Prototype.Browser.WebKit) {
+    window.addEventListener('unload', Prototype.emptyFunction, false);
+  }
+
+  return {
+    observe: function(element, eventName, handler) {
+      element = $(element);
+      var name = getDOMEventName(eventName);
+
+      var wrapper = createWrapper(element, eventName, handler);
+      if (!wrapper) return element;
+
+      if (element.addEventListener) {
+        element.addEventListener(name, wrapper, false);
+      } else {
+        element.attachEvent("on" + name, wrapper);
+      }
+
+      return element;
+    },
+
+    stopObserving: function(element, eventName, handler) {
+      element = $(element);
+      var id = getEventID(element), name = getDOMEventName(eventName);
+
+      if (!handler && eventName) {
+        getWrappersForEventName(id, eventName).each(function(wrapper) {
+          element.stopObserving(eventName, wrapper.handler);
+        });
+        return element;
+
+      } else if (!eventName) {
+        Object.keys(getCacheForID(id)).each(function(eventName) {
+          element.stopObserving(eventName);
+        });
+        return element;
+      }
+
+      var wrapper = findWrapper(id, eventName, handler);
+      if (!wrapper) return element;
+
+      if (element.removeEventListener) {
+        element.removeEventListener(name, wrapper, false);
+      } else {
+        element.detachEvent("on" + name, wrapper);
+      }
+
+      destroyWrapper(id, eventName, handler);
+
+      return element;
+    },
+
+    fire: function(element, eventName, memo) {
+      element = $(element);
+      if (element == document && document.createEvent && !element.dispatchEvent)
+        element = document.documentElement;
+
+      var event;
+      if (document.createEvent) {
+        event = document.createEvent("HTMLEvents");
+        event.initEvent("dataavailable", true, true);
+      } else {
+        event = document.createEventObject();
+        event.eventType = "ondataavailable";
+      }
+
+      event.eventName = eventName;
+      event.memo = memo || { };
+
+      if (document.createEvent) {
+        element.dispatchEvent(event);
+      } else {
+        element.fireEvent(event.eventType, event);
+      }
+
+      return Event.extend(event);
+    }
+  };
+})());
+
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+  fire:          Event.fire,
+  observe:       Event.observe,
+  stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+  fire:          Element.Methods.fire.methodize(),
+  observe:       Element.Methods.observe.methodize(),
+  stopObserving: Element.Methods.stopObserving.methodize(),
+  loaded:        false
+});
+
+(function() {
+  /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+     Matthias Miller, Dean Edwards and John Resig. */
+
+  var timer;
+
+  function fireContentLoadedEvent() {
+    if (document.loaded) return;
+    if (timer) window.clearInterval(timer);
+    document.fire("dom:loaded");
+    document.loaded = true;
+  }
+
+  if (document.addEventListener) {
+    if (Prototype.Browser.WebKit) {
+      timer = window.setInterval(function() {
+        if (/loaded|complete/.test(document.readyState))
+          fireContentLoadedEvent();
+      }, 0);
+
+      Event.observe(window, "load", fireContentLoadedEvent);
+
+    } else {
+      document.addEventListener("DOMContentLoaded",
+        fireContentLoadedEvent, false);
+    }
+
+  } else {
+    document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+    $("__onDOMContentLoaded").onreadystatechange = function() {
+      if (this.readyState == "complete") {
+        this.onreadystatechange = null;
+        fireContentLoadedEvent();
+      }
+    };
+  }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+  Before: function(element, content) {
+    return Element.insert(element, {before:content});
+  },
+
+  Top: function(element, content) {
+    return Element.insert(element, {top:content});
+  },
+
+  Bottom: function(element, content) {
+    return Element.insert(element, {bottom:content});
+  },
+
+  After: function(element, content) {
+    return Element.insert(element, {after:content});
+  }
+};
+
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
+var Position = {
+  // set to true if needed, warning: firefox performance problems
+  // NOT neeeded for page scrolling, only if draggable contained in
+  // scrollable elements
+  includeScrollOffsets: false,
+
+  // must be called before calling withinIncludingScrolloffset, every time the
+  // page is scrolled
+  prepare: function() {
+    this.deltaX =  window.pageXOffset
+                || document.documentElement.scrollLeft
+                || document.body.scrollLeft
+                || 0;
+    this.deltaY =  window.pageYOffset
+                || document.documentElement.scrollTop
+                || document.body.scrollTop
+                || 0;
+  },
+
+  // caches x/y coordinate pair to use with overlap
+  within: function(element, x, y) {
+    if (this.includeScrollOffsets)
+      return this.withinIncludingScrolloffsets(element, x, y);
+    this.xcomp = x;
+    this.ycomp = y;
+    this.offset = Element.cumulativeOffset(element);
+
+    return (y >= this.offset[1] &&
+            y <  this.offset[1] + element.offsetHeight &&
+            x >= this.offset[0] &&
+            x <  this.offset[0] + element.offsetWidth);
+  },
+
+  withinIncludingScrolloffsets: function(element, x, y) {
+    var offsetcache = Element.cumulativeScrollOffset(element);
+
+    this.xcomp = x + offsetcache[0] - this.deltaX;
+    this.ycomp = y + offsetcache[1] - this.deltaY;
+    this.offset = Element.cumulativeOffset(element);
+
+    return (this.ycomp >= this.offset[1] &&
+            this.ycomp <  this.offset[1] + element.offsetHeight &&
+            this.xcomp >= this.offset[0] &&
+            this.xcomp <  this.offset[0] + element.offsetWidth);
+  },
+
+  // within must be called directly before
+  overlap: function(mode, element) {
+    if (!mode) return 0;
+    if (mode == 'vertical')
+      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+        element.offsetHeight;
+    if (mode == 'horizontal')
+      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+        element.offsetWidth;
+  },
+
+  // Deprecation layer -- use newer Element methods now (1.5.2).
+
+  cumulativeOffset: Element.Methods.cumulativeOffset,
+
+  positionedOffset: Element.Methods.positionedOffset,
+
+  absolutize: function(element) {
+    Position.prepare();
+    return Element.absolutize(element);
+  },
+
+  relativize: function(element) {
+    Position.prepare();
+    return Element.relativize(element);
+  },
+
+  realOffset: Element.Methods.cumulativeScrollOffset,
+
+  offsetParent: Element.Methods.getOffsetParent,
+
+  page: Element.Methods.viewportOffset,
+
+  clone: function(source, target, options) {
+    options = options || { };
+    return Element.clonePosition(target, source, options);
+  }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+  function iter(name) {
+    return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+  }
+
+  instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+  function(element, className) {
+    className = className.toString().strip();
+    var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+    return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+  } : function(element, className) {
+    className = className.toString().strip();
+    var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+    if (!classNames && !className) return elements;
+
+    var nodes = $(element).getElementsByTagName('*');
+    className = ' ' + className + ' ';
+
+    for (var i = 0, child, cn; child = nodes[i]; i++) {
+      if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+          (classNames && classNames.all(function(name) {
+            return !name.toString().blank() && cn.include(' ' + name + ' ');
+          }))))
+        elements.push(Element.extend(child));
+    }
+    return elements;
+  };
+
+  return function(className, parentElement) {
+    return $(parentElement || document.body).getElementsByClassName(className);
+  };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+  initialize: function(element) {
+    this.element = $(element);
+  },
+
+  _each: function(iterator) {
+    this.element.className.split(/\s+/).select(function(name) {
+      return name.length > 0;
+    })._each(iterator);
+  },
+
+  set: function(className) {
+    this.element.className = className;
+  },
+
+  add: function(classNameToAdd) {
+    if (this.include(classNameToAdd)) return;
+    this.set($A(this).concat(classNameToAdd).join(' '));
+  },
+
+  remove: function(classNameToRemove) {
+    if (!this.include(classNameToRemove)) return;
+    this.set($A(this).without(classNameToRemove).join(' '));
+  },
+
+  toString: function() {
+    return $A(this).join(' ');
+  }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods();
\ No newline at end of file
diff --git a/website/quick_start.html b/website/quick_start.html
new file mode 100644 (file)
index 0000000..e74d380
--- /dev/null
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE html PUBLIC "XHTML 1.0 Strict" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<meta name="Last-modified" content="Mon, 4 Apr 2011 12:00:00 GMT"/>\r
+<title>Java Bioinformatics Analyses Web Services (JABAWS) manual - getting started</title>\r
+<link href="ws.css" rel="stylesheet" type="text/css" media="screen,  projection, handheld, tv" />\r
+<link rel="stylesheet" type="text/css" media="print" href="print.css"/>\r
+\r
+<script type="text/javascript" src="prototype-1.6.0.3.js"></script>\r
+</head>\r
+<body>\r
+<div id="page">\r
+<div id="banner"><table> \r
+<tr><td style="width:130px;"><a href="http://www.dundee.ac.uk"><img src="images/uod_lt.gif"  alt="University of Dundee" class="logo"  title="University of Dundee" longdesc="http://www.dundee.ac.uk"/></a></td>\r
+<td class="bg"><img src="images/jabaws.png" title="JABAWS:MSA" alt="JABAWS:MSA"/></td>\r
+<td class="bg"><img src="images/align.png"/></td>\r
+</tr>\r
+</table>\r
+</div><!-- banner end-->\r
+<div id="wrapper">\r
+<div id="panel">\r
+       <a href="index.html">Home</a>\r
+    <a class="selected" href="quick_start.html">Getting Started</a> \r
+    <a href="man_about.html">Manual</a> \r
+       <a href="download.html">Download</a>\r
+       <a href="contacts.html">Contact Us</a>\r
+       <a href="http://www.compbio.dundee.ac.uk">Barton Group</a></div>\r
+<!-- panel end-->\r
+<div id="content">\r
+\r
+<h2 id="headtitle">Getting Started</h2>\r
+\r
+<h3><a name="whichjaba" id="whichjaba"></a>Choose a JABAWS distribution</h3>\r
+\r
+<table id="choicematrix">\r
+<tr>\r
+  <th>I want to use JABAWS for...</th>\r
+  <th>Quick Guide</th>\r
+</tr>\r
+<tr>\r
+       <td>Running Muptiple Sequence Alignments through Jalview on my <strong>own</strong> computer</td>\r
+    <td><a href="manual_qs_va.html#qsc">JABAWS Virtual Appliance (VA)</a></td>\r
+</tr>\r
+<tr>\r
+       <td>Running JABAWS for my group, lab, or organization</td>\r
+    <td><a href="manual_qs_war.html#qsc">JABAWS Web Application aRchive (WAR)</a></td>\r
+</tr>\r
+<tr>\r
+       <td>Accessing a JABAWS server from my own code</td>\r
+    <td><a href="manual_qs_client.html#qsc">JABAWS Java Client</a></td>\r
+</tr>\r
+</table>\r
+\r
+\r
+\r
+\r
+\r
+<!-- about end-->\r
+</div>\r
+<!-- content end--> \r
+<div id="copyright">Last update: 1 April 2011<br/>\r
+Peter Troshin, Jim Procter and Geoff Barton, The Barton Group, University of Dundee, UK</div>\r
+</div><!-- wrapper end-->\r
+</div> <!-- page end-->\r
+\r
+<!-- Google analitics -->\r
+<script type="text/javascript">\r
+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");\r
+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));\r
+</script>\r
+<script type="text/javascript">\r
+try{\r
+var pageTracker = _gat._getTracker("UA-5356328-1");\r
+pageTracker._trackPageview();\r
+} catch(err) {}\r
+</script>\r
+</body>\r
+</html>\r
+\r
diff --git a/website/ws.css b/website/ws.css
new file mode 100644 (file)
index 0000000..5d9156c
--- /dev/null
@@ -0,0 +1,379 @@
+\r
+#banner { background-color:white; }\r
+\r
+#mainpagefeatures {\r
+   margin: 0 2em 0 2em;\r
+}\r
+\r
+#wrapper #mainpagefeatures table, #wrapper #mainpagefeatures th, #wrapper #mainpagefeatures td, #wrapper #mainpagefeatures tr{\r
+  border:none;\r
+  border-collapse:collapse;\r
+  background-color: #fff; \r
+  padding-bottom:2em;\r
+}\r
+\r
+#wrapper #choicematrix table, #wrapper #choicematrix th, #wrapper #choicematrix td, #wrapper #choicematrix tr{\r
+  border:1px solid grey;\r
+  background-color: #fff; \r
+  padding:1em;\r
+}\r
+\r
+#wrapper #choicematrix th {\r
+  background-image:url(images/brickhead2.jpg); \r
+  background-repeat:repeat-x;\r
+}\r
+\r
+.brick {\r
+padding-bottom:1em;\r
+    border: 2px solid #999;\r
+    -webkit-border-radius:20px;\r
+    -moz-border-radius:20px;\r
+       border-radius: 20px;\r
+    background-image:url(images/brickhead2_line.jpg);\r
+    background-repeat:repeat-x;\r
+}\r
+.brick_header {\r
+    display:block;\r
+       background:none;\r
+}\r
+\r
+.brick_header h2 {\r
+    font-weight: bold;\r
+       border:none;\r
+       background:none;\r
+       margin: 0.7em 0 0 0.5em;\r
+}\r
+\r
+.brick_content {\r
+  position:relative;\r
+  padding: 2em 1.5em 0em 1.5em;\r
+}\r
+\r
+\r
+/*\r
+td.vm {\r
+background-image:url(images/N_cell.jpg);\r
+background-repeat:repeat-x;\r
+}\r
+td.button a {\r
+display:block;\r
+background:#069;\r
+border:1px outset #069;\r
+text-decoration:none;\r
+font-weight:bold;\r
+line-height:1.5em;\r
+padding:0 .5em;\r
+color:#fff;\r
+}\r
+\r
+td.button a:hover {\r
+background:#09c;\r
+border-color:09c;\r
+}\r
+*/\r
+#container .round {\r
+    display:block;\r
+    margin-right:10px;\r
+    background:#fff;\r
+    border: 1px solid #ccc;\r
+    -webkit-border-radius:20px;\r
+    -moz-border-radius:20px;\r
+       border-radius: 20px;\r
+    background-image:url(images/N_cell.jpg);\r
+    background-repeat:repeat-x;\r
+}\r
\r
+ /*\r
+#container .example5 div a {\r
+    padding:3px 20px;\r
+    border: 1px solid #ccc;\r
+    -webkit-border-radius:20px;\r
+    -moz-border-radius:15px;\r
+}\r
\r
+#container .example5 div a:hover {\r
+    background:#5d9ddd;\r
+    border:1px solid #2a7ecd;\r
+    color:#fff;\r
+}\r
+*/\r
+/*\r
+\r
+  -webkit-border-radius:20px;\r
+    -moz-border-radius:15px;\r
+       \r
+See index.html banner commented out code for an example of use \r
+.uniicon { overflow: hidden; display:inline; padding:0; margin:0; float:right; position:relative; top:1em; } \r
+.uniicon a img {border:none;} \r
+*/\r
+#panel { \r
+       width:150px; \r
+       background:url("images/panel_bg.gif") repeat-y ; \r
+       float:left;\r
+       font-family:Verdana, Arial, Helvetica, sans-serif;\r
+       padding-top:1em;\r
+ }\r
+\r
+#content { \r
+      margin-left:157px; \r
+      border-bottom:solid 1px #6994af; \r
+         margin-right:0.9em;\r
+}\r
+\r
+#page { \r
+  margin: 0;\r
+  background-color:#fff;\r
+}\r
+\r
+#copyright { text-align:right; \r
+                        color:#999999; \r
+                        font-family:Verdana, Arial, Helvetica, sans-serif;\r
+                        font-size:smaller;\r
+                        line-height:1em;\r
+                        padding:0.3em 0.9em 1em 0;\r
+ }\r
+\r
+#wrapper { \r
+    background:url("images/panel_bg.gif") repeat-y left top; \r
+    margin:0; \r
+    padding:0; \r
+}\r
+\r
+ul {\r
+       list-style-type: circle;\r
+}\r
+\r
+#panel a:link, #panel a:visited {\r
+           text-decoration: none;\r
+               display:block;\r
+               line-height: 1em;\r
+               padding:10px;\r
+               color:#000000; \r
+        }\r
+        \r
+#panel a:hover {\r
+           background-color: transparent;\r
+           text-decoration: underline;\r
+       }\r
+\r
+#panel a.selected {\r
+ text-decoration:underline; \r
+ font-weight:bolder;\r
+}\r
+\r
+\r
+#panel #submenu a {\r
+margin-left: 1.5em;\r
+margin-left: 20px;\r
+padding: 5px; \r
+}\r
+\r
+strong {\r
+       font-weight:bold;\r
+       color:#003366;\r
+}\r
+\r
+pre {\r
+       font-family:Arial, Helvetica, sans-serif;\r
+}\r
+\r
+p { \r
+       line-height: 1.4em;\r
+}\r
\r
+.hightlight { \r
+font-style:italic;\r
+font-family:"Courier New", Courier, monospace;\r
+}\r
+\r
+\r
+/*\r
+.about {\r
+border-left: solid 4px #006633;\r
+border-left-style:ridged;\r
+padding-left: 1em;\r
+}*/\r
+\r
+\r
+.code { \r
+       color:black;\r
+       background-color:#F5F5F5;\r
+       font-family:"Courier New",Courier,monospace;\r
+       font-style:normal;\r
+       margin:1em 0;\r
+       padding: 0.5em;\r
+       border: 1px dashed black;\r
+       display:block;\r
+}\r
+\r
+.box { \r
+       color:black;\r
+       background-color:#F5F5F5;\r
+       font-family:Arial, Helvetica, sans-serif;\r
+       font-style:normal;\r
+       margin:1em 0;\r
+       padding: 0.5em;\r
+       border: 1px solid black;\r
+       display:block;\r
+}\r
+\r
+.u { text-decoration: underline; }\r
+/* .headeru { text-shadow: #CCCCCC 15px -14px 2px;}  font-size-adjust:+0.7 */\r
+/*.headeru { text-shadow:  1px 0 black, 0 -1px black;}  */\r
+.headeru { \r
+               text-shadow:0 1px 3px black;\r
+               border-bottom: 1px solid white;\r
+} \r
+/* .headeru { border-bottom:1px solid white; }  */\r
+\r
+#banner h1 { \r
+       font-family:Helvetica, Arial, sans-serif;\r
+       white-space:nowrap;\r
+    color: white;\r
+       font-weight:bold;\r
+       text-shadow:0 1px 3px #100F0E;\r
+    font-size: 27px;\r
+}\r
+\r
+h3 {border-bottom: 1px solid grey; margin-top: 2em; }\r
+\r
+#headtitle { margin:0; padding-top:1em; text-align:center; color:#003b62; font-weight:600;} \r
+\r
+h2 {margin:1.8em 0 0 0; color:#003b62; font-weight:600;}\r
+\r
+/* Table styles */\r
+\r
+#wrapper table {\r
+       border-collapse: collapse; \r
+       border: 1px solid #666;\r
+       margin: 20px 0 20px 0;\r
+       width: 100%;\r
+}\r
+#wrapper th, #wrapper td {\r
+       margin: 2px 4px 2px 4px;\r
+       padding: 0 5px;\r
+       text-align: left;\r
+       vertical-align: top;\r
+       border: 1px solid #666;\r
+}\r
+\r
+#wrapper table caption {\r
+       font: 1.5em Georgia, "Times New Roman", Times, serif; \r
+       padding: 1em;\r
+       background-color: #9c9;\r
+}\r
+\r
+\r
+#wrapper tr {\r
+        background-color: #eee; \r
+}\r
+\r
+#wrapper tr:nth-child(odd) {\r
+        background-color: #ccc; \r
+}\r
+\r
+span.directory {\r
+background: transparent url(images/dir.gif) no-repeat scroll left center;\r
+color:#666666;\r
+font-family:"Courier New",Courier,monospace;\r
+font-style:normal;\r
+padding:0 0 0 15px;\r
+}\r
+\r
+.attention { \r
+color:#993333;\r
+}\r
+\r
+/* open/closed box related styles */\r
+\r
+.source { \r
+       border:1px solid #858789;\r
+       display:block;\r
+       margin:26px 0;\r
+       overflow:visible;\r
+}\r
+\r
+/* OPEN state styles */\r
+.source .body {\r
+       background:#F5F5F5 none repeat scroll right 0;\r
+       color:#434546;\r
+       padding:7px 15px;\r
+/*     white-space:pre-wrap; */\r
+       white-space:normal;\r
+/*     word-wrap:break-word; # this prop does not exits*/\r
+}\r
+\r
+.source .header {\r
+       background:#E9EAEC url(images/minus.png) no-repeat scroll 98% center;\r
+       color:#3B3D3F;\r
+       cursor:pointer;\r
+       font-weight:bold;\r
+       height:30px;\r
+       line-height:30px;\r
+       padding:0 15px 0 15px;\r
+}\r
+\r
+/* CLOSED state styles */\r
+.source .body.collapsed {\r
+       display:none;\r
+}\r
+\r
+.source .header.collapsed  {\r
+       background:#E9EAEC url(images/plus.png) no-repeat scroll 98% center;\r
+       padding:0 15px 0 15px;\r
+}\r
+\r
+.body .code { \r
+       margin:0;\r
+       padding:0;\r
+       border:0;\r
+       font-family:"Courier New",Courier,monospace;\r
+       font-style:normal;\r
+}\r
+\r
+body {\r
+       font-family:Arial, Helvetica, sans-serif;\r
+       /*      color: #494949; */\r
+    font: 12px/170% Verdana;\r
+       background-image:url(images/matrix_bg6.jpg);\r
+       background-repeat:repeat;\r
+/*     background-color: #EAEAEA; */\r
+       line-height: 2em;\r
+       min-width: 760px;\r
+       max-width: 1100px;\r
+       margin:0 auto;\r
+}\r
+\r
+\r
+#banner table {\r
+       border-collapse: collapse; \r
+       border: none;\r
+       padding:0;\r
+       margin:0;\r
+       line-height:0.5em;\r
+       color:white;\r
+       text-align:center;\r
+       vertical-align:middle;\r
+       width: 100%;\r
+}\r
+\r
+\r
+#banner td.bg  {\r
+       border-collapse: collapse; \r
+       background-image:url("images/banner_bg.gif");\r
+       background-repeat: repeat-x; \r
+       background-color:transparent;\r
+       background-position:inherit;\r
+}\r
+\r
+img.logo  {\r
+/*     border-top:1px solid #003b62; \r
+       border-left:1px solid #003b62; \r
+       border-right:none; \r
+       border-bottom: none; */\r
+       border:none;\r
+       margin:0; \r
+       padding:0; \r
+       display:inline\r
+       float:left;\r
+}\r