[med-svn] [freeshim] 07/09: New upstream version 0.1.1+20150629

Andreas Tille tille at debian.org
Wed Dec 27 23:20:51 UTC 2017


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository freeshim.

commit e00bed33e7873f73aa097bae38b7283972574ef8
Author: Andreas Tille <tille at debian.org>
Date:   Thu Dec 28 00:19:32 2017 +0100

    New upstream version 0.1.1+20150629
---
 .gitignore                                         |   4 +
 .project                                           |  17 +
 .settings/org.maven.ide.eclipse.prefs              |   9 +
 .travis.yml                                        |   5 +
 LICENSE                                            |  48 +
 README.md                                          |  47 +
 assembly/dist.xml                                  |  44 +
 build-free.sh                                      |  58 ++
 debian/changelog                                   |   8 -
 debian/compat                                      |   1 -
 debian/control                                     |  30 -
 debian/copyright                                   |  37 -
 debian/dirs                                        |   2 -
 debian/docs                                        |   2 -
 debian/get-orig-source                             |  25 -
 debian/maven.cleanIgnoreRules                      |  17 -
 debian/maven.ignoreRules                           |  16 -
 debian/maven.publishedRules                        |  19 -
 debian/maven.rules                                 |  21 -
 debian/patches/no_maven-javadoc-plugin.patch       | 222 -----
 debian/patches/series                              |   2 -
 debian/patches/use_debian_maven_settings.patch     |  11 -
 debian/rules                                       |   8 -
 debian/shim.poms                                   |  34 -
 debian/source/format                               |   1 -
 git2cl                                             | 372 ++++++++
 pom.xml                                            |  42 +
 project.properties                                 |   1 +
 remove-nonfree.xsl                                 |  22 +
 shim-drivers/.project                              |  17 +
 shim-drivers/.settings/org.maven.ide.eclipse.prefs |   9 +
 shim-drivers/README                                |   5 +
 shim-drivers/pom.xml                               |  26 +
 shim-drivers/shim-driver-dosing-scilog/.classpath  |   8 +
 shim-drivers/shim-driver-dosing-scilog/.project    |  26 +
 .../.settings/org.eclipse.jdt.core.prefs           |   9 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 .../.settings/org.maven.ide.eclipse.prefs          |   9 +
 shim-drivers/shim-driver-dosing-scilog/pom.xml     |  86 ++
 .../device/impl/DosingPumpScilogShim.java          | 121 +++
 shim-drivers/shim-driver-lab-clinitek50/.classpath |   9 +
 shim-drivers/shim-driver-lab-clinitek50/.project   |  26 +
 .../.settings/org.eclipse.jdt.core.prefs           |   9 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 .../.settings/org.maven.ide.eclipse.prefs          |   9 +
 shim-drivers/shim-driver-lab-clinitek50/pom.xml    |  86 ++
 .../device/impl/LabClinitek50Shim.java             | 378 ++++++++
 .../shim-driver-lab-microlab3500/.classpath        |   9 +
 shim-drivers/shim-driver-lab-microlab3500/.project |  26 +
 .../.settings/org.eclipse.jdt.core.prefs           |   9 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 .../.settings/org.maven.ide.eclipse.prefs          |   9 +
 .../doc/SerialML3500.doc                           | Bin 0 -> 101888 bytes
 shim-drivers/shim-driver-lab-microlab3500/pom.xml  |  86 ++
 .../device/impl/LabMicroLab3500Shim.java           | 302 +++++++
 shim-drivers/shim-driver-label-escpos/.classpath   |   8 +
 shim-drivers/shim-driver-label-escpos/.project     |  36 +
 .../.settings/org.eclipse.jdt.core.prefs           |   9 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 .../.settings/org.maven.ide.eclipse.prefs          |   9 +
 shim-drivers/shim-driver-label-escpos/pom.xml      |  92 ++
 .../device/impl/LabelEscPosShim.java               | 218 +++++
 .../main/resources/templates/dosinglabel.template  |  80 ++
 .../src/main/resources/templates/toxlabel.template |  53 ++
 .../shim-driver-signature-dummy/.classpath         |   8 +
 shim-drivers/shim-driver-signature-dummy/.project  |  36 +
 .../.settings/org.eclipse.jdt.core.prefs           |   9 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 .../.settings/org.maven.ide.eclipse.prefs          |   9 +
 shim-drivers/shim-driver-signature-dummy/pom.xml   |  77 ++
 .../device/impl/SignatureDummyShim.java            | 114 +++
 .../shim-driver-signature-topaz/.classpath         |   9 +
 shim-drivers/shim-driver-signature-topaz/.project  |  36 +
 .../.settings/org.eclipse.jdt.core.prefs           |   9 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 .../.settings/org.maven.ide.eclipse.prefs          |   9 +
 shim-drivers/shim-driver-signature-topaz/README    |  22 +
 .../deps/commapi-2.0.3.jar                         | Bin 0 -> 29890 bytes
 .../deps/sigplus-2.60.jar                          | Bin 0 -> 119781 bytes
 .../native/i686-unknown-linux-gnu/libSigUsb.so     | Bin 0 -> 105618 bytes
 .../native/win32/SigUsb.dll                        | Bin 0 -> 73728 bytes
 .../native/win32/TopazAuto.inf                     |  60 ++
 .../native/win32/TopazUsb.sys                      | Bin 0 -> 33716 bytes
 shim-drivers/shim-driver-signature-topaz/pom.xml   |  89 ++
 .../device/impl/SignatureTopazShim.java            | 598 +++++++++++++
 shim-drivers/shim-driver-signature-topaz/test.sh   |  31 +
 shim-library/.classpath                            |   9 +
 shim-library/.project                              |  36 +
 shim-library/.settings/org.eclipse.jdt.core.prefs  |  13 +
 .../.settings/org.eclipse.wst.common.component     |   6 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 shim-library/.settings/org.maven.ide.eclipse.prefs |   9 +
 shim-library/deps/extcos-0.1.1b.jar                | Bin 0 -> 170724 bytes
 shim-library/deps/extcos-0.1b.jar                  | Bin 0 -> 171279 bytes
 shim-library/deps/rxtx-2.2pre2.jar                 | Bin 0 -> 60866 bytes
 .../i686-unknown-linux-gnu/librxtxParallel.so      | Bin 0 -> 60041 bytes
 .../native/i686-unknown-linux-gnu/librxtxSerial.so | Bin 0 -> 154682 bytes
 .../native/ia64-unknown-linux-gnu/librxtxSerial.so | Bin 0 -> 188377 bytes
 shim-library/native/win32/rxtxSerial.dll           | Bin 0 -> 122880 bytes
 shim-library/native/win64/rxtxSerial.dll           | Bin 0 -> 128000 bytes
 .../x86_64-unknown-linux-gnu/librxtxParallel.so    | Bin 0 -> 53652 bytes
 .../x86_64-unknown-linux-gnu/librxtxSerial.so      | Bin 0 -> 181421 bytes
 shim-library/pom.xml                               | 122 +++
 .../freemedsoftware/device/DeviceCapability.java   |  42 +
 .../freemedsoftware/device/DeviceInterface.java    |  52 ++
 .../freemedsoftware/device/DosingPumpCommand.java  |  41 +
 .../device/DosingPumpInterface.java                |  43 +
 .../device/DosingPumpSerialInterface.java          | 146 +++
 .../org/freemedsoftware/device/JobStoreItem.java   | 145 +++
 .../freemedsoftware/device/LabSerialInterface.java | 146 +++
 .../device/LabelPrinterInterface.java              |  39 +
 .../device/ParallelPrinterInterface.java           | 121 +++
 .../freemedsoftware/device/PersistentJobStore.java |  43 +
 .../device/PersistentJobStoreDAO.java              | 280 ++++++
 .../freemedsoftware/device/SerialInterface.java    | 137 +++
 .../org/freemedsoftware/device/ShimDevice.java     |  37 +
 .../freemedsoftware/device/ShimDeviceManager.java  | 190 ++++
 .../freemedsoftware/device/SignatureInterface.java |  35 +
 .../org/freemedsoftware/device/impl/DummyShim.java |  68 ++
 .../device/types/AbnormalFlagCode.java             |  46 +
 .../freemedsoftware/device/types/ObrRecord.java    |  77 ++
 .../freemedsoftware/device/types/ObxRecord.java    |  88 ++
 .../device/types/SpecimenSourceCode.java           |  65 ++
 .../device/ShimDeviceManagerTest.java              |  41 +
 shim-webapp/.classpath                             |   9 +
 shim-webapp/.project                               |  42 +
 shim-webapp/.settings/.jsdtscope                   |  11 +
 shim-webapp/.settings/org.eclipse.jdt.core.prefs   |   9 +
 .../.settings/org.eclipse.wst.common.component     |  21 +
 .../org.eclipse.wst.common.project.facet.core.xml  |   5 +
 .../org.eclipse.wst.jsdt.ui.superType.container    |   1 +
 .../org.eclipse.wst.jsdt.ui.superType.name         |   1 +
 shim-webapp/.settings/org.maven.ide.eclipse.prefs  |   9 +
 shim-webapp/README                                 |  98 ++
 shim-webapp/jetty-realm.properties                 |   1 +
 shim-webapp/packaging/win32/INSTALLLICENSE         | 991 +++++++++++++++++++++
 shim-webapp/packaging/win32/build.sh               |  25 +
 shim-webapp/packaging/win32/config.ini             |  58 ++
 .../packaging/win32/confinstall/server_1.xml       |  69 ++
 .../packaging/win32/confinstall/server_2.xml       |  80 ++
 .../packaging/win32/confinstall/tomcat-users_1.xml |  17 +
 .../packaging/win32/confinstall/tomcat-users_2.xml |  13 +
 shim-webapp/packaging/win32/header.bmp             | Bin 0 -> 9742 bytes
 shim-webapp/packaging/win32/jvm.ini                |  18 +
 shim-webapp/packaging/win32/main.ico               | Bin 0 -> 766 bytes
 shim-webapp/packaging/win32/shim.nsi               | 822 +++++++++++++++++
 shim-webapp/packaging/win32/side_left.bmp          | Bin 0 -> 117390 bytes
 shim-webapp/packaging/win32/tickno.bmp             | Bin 0 -> 358 bytes
 shim-webapp/packaging/win32/tickyes.bmp            | Bin 0 -> 358 bytes
 shim-webapp/packaging/win32/tomcat.ico             | Bin 0 -> 21630 bytes
 shim-webapp/packaging/win32/uninst.ico             | Bin 0 -> 766 bytes
 shim-webapp/packaging/win32/welcome.bin.html       |  87 ++
 shim-webapp/packaging/win32/welcome.main.html      |  87 ++
 shim-webapp/pom.xml                                | 146 +++
 .../org/freemedsoftware/shim/Configuration.java    | 124 +++
 .../java/org/freemedsoftware/shim/Constants.java   |  29 +
 .../org/freemedsoftware/shim/HashMapEntryType.java |  38 +
 .../java/org/freemedsoftware/shim/HashMapType.java |  33 +
 .../freemedsoftware/shim/HashMapXmlAdapter.java    |  57 ++
 .../org/freemedsoftware/shim/LoggerServlet.java    |  91 ++
 .../freemedsoftware/shim/MasterControlServlet.java | 328 +++++++
 .../shim/ShimDeviceInformation.java                |  65 ++
 .../java/org/freemedsoftware/shim/ShimService.java |  76 ++
 .../org/freemedsoftware/shim/ShimServiceImpl.java  | 187 ++++
 .../org/freemedsoftware/shim/SignatureStatus.java  |  54 ++
 .../exception/DeviceNotAvailableException.java     |  31 +
 .../src/main/webapp/WEB-INF/cxf-servlet.xml        |  19 +
 shim-webapp/src/main/webapp/WEB-INF/cxf.xml        |  66 ++
 .../src/main/webapp/WEB-INF/log4j.properties       |  35 +
 .../main/webapp/WEB-INF/shim-default.properties    |  57 ++
 shim-webapp/src/main/webapp/WEB-INF/web.xml        | 106 +++
 shim-webapp/src/main/webapp/admin/control.jsp      |  88 ++
 shim-webapp/src/main/webapp/admin/index.jsp        |  44 +
 shim-webapp/src/main/webapp/admin/status.jsp       | 101 +++
 shim-webapp/src/main/webapp/img/freeshim.png       | Bin 0 -> 5929 bytes
 shim-webapp/src/main/webapp/index.jsp              |  43 +
 shim-webapp/test/soap-client.php                   |  78 ++
 183 files changed, 10082 insertions(+), 456 deletions(-)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0195948
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+shim-drivers/*/target
+shim-library/target
+shim-webapp/target
+shim-*-dist.*
diff --git a/.project b/.project
new file mode 100644
index 0000000..516cb72
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>shim</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/.settings/org.maven.ide.eclipse.prefs b/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..ec8e7f7
--- /dev/null
+++ b/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Fri Jul 30 13:06:04 EDT 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..e7dd056
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,5 @@
+language: java
+jdk:
+  - oraclejdk8
+  - openjdk7
+  - openjdk6
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..1bad479
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,48 @@
+$Id$
+FreeSHIM Licencing Information
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Suite 500, Boston, MA 02110, USA.
+
+------------------------------------------------------------------------
+
+TOPAZ SYSTEMS DRIVER / SOFTWARE LICENSING INFORMATION:
+
+The closed-source (but freely available) Topaz JNI and Java JAR components
+included with the source code and/or distribution were downloaded from
+http://www.topazsystems.com/software/download/java/index.htm ; more
+information on licensing and use of their software and hardware is available
+at http://www.topazsystems.com/information/legal.htm 
+
+The pertinent sections of that document are:
+
+Any software that is available on this Site ("Software") is the copyrighted
+work of Topaz Systems, Inc. and/or its licensors. Copying or reproducing the
+Software to any other server or location for further reproduction or
+redistribution is prohibited, unless such reproduction or redistribution is
+permitted by a license agreement accompanying such Software. You may not
+attempt to decompile or reverse-engineer the Software unless otherwise
+permitted by law. Use of the Software is subject to the license terms of any
+license agreement that may accompany or is provided with the Software.
+
+WITHOUT LIMITING THE FOREGOING, THE SOFTWARE IS WARRANTED, IF AT ALL, ONLY
+ACCORDING TO THE TERMS OF A SEPARATE LICENSE AGREEMENT ACCOMPANYING THE
+SOFTWARE. EXCEPT AS WARRANTED IN SUCH LICENSE AGREEMENT, TOPAZ SYSTEMS, INC.,
+DISCLAIMS ALL WARRANTIES AND CONDITIONS WITH REGARD TO THE SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT, TO THE MAXIMUM EXTENT PERMITTED
+BY LAW.
+
+------------------------------------------------------------------------
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..9771eb9
--- /dev/null
+++ b/README.md
@@ -0,0 +1,47 @@
+# FreeSHIM Opensource Multiplatform Medical Device Interface
+
+* (c) 2011-2014 by the FreeMED Software Foundation
+
+## INSTALLATION
+
+* The generated "shim.war" file needs to be dropped into the webapps
+ folder of your Tomcat installation. If you don't have a "shim.war"
+  file, please see the "COMPILATION" section.
+
+* If you need to use any of the "native libraries" for any of the 
+  device drivers, follow their respective README files for instructions
+  on how to install their JNI libraries. (If there are any.) Maven
+  *should* handle this for you.
+
+* If you're using a serial port, you may have to run "setserial" on it,
+  or even bake that into your /etc/rc.local file to run on boot, otherwise
+  some dosing pumps, etc, may not work!
+
+* Really, that's it. It's very simple. A more "in-depth" document for
+  shim.war is located in shim-webapp/README !
+
+## CONFIGURATION
+
+* FreeSHIM uses a set of defaults which are included with it. These
+  are viewable here (with documentation, of course): https://github.com/freemed/freeshim/blob/master/shim-webapp/src/main/webapp/WEB-INF/shim-default.properties
+*  To override these, pass ```-Dshim.properties=/path/to/your/shim.properties``` to your J2EE container.
+
+## COMPILATION
+
+* Install Maven 2 and JDK 1.6 on your system.
+* Ask Maven to package the system: `mvn package`
+* Voila! You should see the "shim.war" package in `shim-webapps/target/`
+
+## CAVEATS
+
+Due to certain device manufacturers not liking to "play nice" with
+open source efforts, there are a certain number of JNI (Java Native
+Interface) libraries used. These are architecture specific, and it is
+somewhat likely that they may not exist for all target architectures,
+so there is always the outside chance that, for example, a 32-bit
+Linux JVM might support more drivers than a 64-bit one (same with the
+Windows builds). If you don't like that, bother the manufacturers who
+have saddled us with fewer than the appropriate number of architecture
+builds, or feel free to write an opensource equivalent. We're partial
+to the latter solution. ;)
+
diff --git a/assembly/dist.xml b/assembly/dist.xml
new file mode 100644
index 0000000..ed563a1
--- /dev/null
+++ b/assembly/dist.xml
@@ -0,0 +1,44 @@
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" 
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+  <id>${project.version}-dist</id>
+  <formats>
+    <format>tar.gz</format>
+    <format>tar.bz2</format>
+    <format>zip</format>
+  </formats>
+  <fileSets>
+    <fileSet>
+      <directory>${project.basedir}</directory>
+      <outputDirectory>/</outputDirectory>
+      <includes>
+        <include>README*</include>
+        <include>LICENSE*</include>
+        <include>NOTICE*</include>
+        <include>ChangeLog</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>shim-webapp/target</directory>
+      <outputDirectory>/</outputDirectory>
+      <includes>
+        <include>*.war</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>shim-webapp/src/main/webapp/WEB-INF</directory>
+      <outputDirectory>/</outputDirectory>
+      <includes>
+        <include>shim-default.properties</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>shim-library/native</directory>
+      <outputDirectory>/native/library/</outputDirectory>
+    </fileSet>
+    <fileSet>
+      <directory>shim-drivers/shim-driver-signature-topaz/native</directory>
+      <outputDirectory>/native/topaz/</outputDirectory>
+    </fileSet>
+  </fileSets>
+</assembly>
diff --git a/build-free.sh b/build-free.sh
new file mode 100755
index 0000000..84d9b87
--- /dev/null
+++ b/build-free.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+#
+#	$Id$
+#	jeff at freemedsoftware.org
+#
+
+# Build a Debian "free" version of FreeSHIM.
+
+echo "Building changelog ... "
+./git2cl > ChangeLog
+
+echo "Exporting from Subversion ... "
+git archive --remote git://github.com/freemed/freeshim.git master | tar -x -C BUILD
+
+echo "Removing non-free component(s) ... "
+xsltproc remove-nonfree.xsl BUILD/shim-webapp/pom.xml > BUILD/shim-webapp/pom.xml.tmp
+mv BUILD/shim-webapp/pom.xml.tmp BUILD/shim-webapp/pom.xml -f
+xsltproc remove-nonfree.xsl BUILD/shim-drivers/pom.xml > BUILD/shim-drivers/pom.xml.tmp
+mv BUILD/shim-drivers/pom.xml.tmp BUILD/shim-drivers/pom.xml -f
+rm -rf BUILD/shim-drivers/shim-driver-signature-topaz
+
+echo "Moving in changelog ... "
+mv ChangeLog BUILD/ -vf
+
+echo "Creating source archives"
+
+VERSION=$( cat project.properties | grep 'shim.version' | cut -d= -f2 )
+echo "Version $VERSION"
+
+cp BUILD shim-${VERSION} -Rf
+
+zip -r shim-free-${VERSION}-src.zip shim-${VERSION}
+tar czvf shim-free-${VERSION}-src.tar.gz shim-${VERSION}
+rm -rf shim-${VERSION}
+
+(
+
+cd BUILD
+
+echo "Building!"
+mvn
+
+ls -1 shim-*.*
+
+ls -1 shim-*.* | while read X; do
+	Y="${X/shim/shim-free}"
+	mv "$X" "$Y" -vf
+	mv "$Y" .. -vf
+done
+
+cd ..
+
+)
+
+echo "Cleaning..."
+rm BUILD -rf
+echo "done"
+
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100644
index eb89cf4..0000000
--- a/debian/changelog
+++ /dev/null
@@ -1,8 +0,0 @@
-freeshim (0.1.1+20110502-1) UNRELEASED; urgency=low
-
-  * Initial release (Closes: #nnnn)
-  Project does not seem to exist any more since while it has moved to Github
-  there is no recent activity for years and domain http://freeshim.org has been
-  taken over by something really different
-
- -- Jeff Buchbinder <jeff at freemedsoftware.org>  Wed, 20 Apr 2011 10:02:58 -0400
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index f599e28..0000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-10
diff --git a/debian/control b/debian/control
deleted file mode 100644
index 169b25b..0000000
--- a/debian/control
+++ /dev/null
@@ -1,30 +0,0 @@
-Source: freeshim
-Maintainer: Debian Med Packaging Team <debian-med-packaging at lists.alioth.debian.org>
-Uploaders: Jeff Buchbinder <jeff at freemedsoftware.org>,
-           Andreas Tille <tille at debian.org>
-Section: science
-Priority: optional
-Build-Depends: debhelper (>= 10),
-               openjdk-6-jdk,
-               cdbs,
-               maven-debian-helper,
-               maven2,
-               librxtx-java,
-               liblog4j1.2-java,
-               libhsqldb-java
-Standards-Version: 3.9.8
-Vcs-Browser: http://anonscm.debian.org/viewvc/debian-med/trunk/packages/shim/trunk/
-Vcs-Svn: svn://anonscm.debian.org/debian-med/trunk/packages/shim/trunk
-Homepage: https://github.com/freemed/freeshim
-
-Package: freeshim
-Architecture: any
-Depends: ${shlibs:Depends},
-         ${misc:Depends},
-         openjdk-6-jre-headless,
-         librxtx-java
-Description: opensource electronic medical device interface
- FreeSHIM is an opensource electronic medical device interface, which aims
- to allow any EMR/PM system to talk to any medical device attached to a
- workstation without having to install tons of pesky drivers or “reinvent
- the wheel” for each additional device manufacturer.
diff --git a/debian/copyright b/debian/copyright
deleted file mode 100644
index b8165fa..0000000
--- a/debian/copyright
+++ /dev/null
@@ -1,37 +0,0 @@
-This work was packaged for Debian by:
-
-    Jeff Buchbinder <jeff at freemedsoftware.org> on Wed, 20 Apr 2011 10:02:58 -0400
-
-It was downloaded from:
-
-    <url://example.com>
-
-Upstream Author(s):
-
-    <put author's name and email here>
-    <likewise for another author>
-
-Copyright:
-
-    <Copyright (C) YYYY Firstname Lastname>
-    <likewise for another author>
-
-License:
-
-    <Put the license of the package here indented by 4 spaces>
-
-The Debian packaging is:
-
-    Copyright (C) 2011 Jeff Buchbinder <jeff at freemedsoftware.org>
-
-# Please chose a license for your packaging work. If the program you package
-# uses a mainstream license, using the same license is the safest choice.
-# Please avoid to pick license terms that are more restrictive than the
-# packaged work, as it may make Debian's contributions unacceptable upstream.
-# If you just want it to be GPL version 3, leave the following lines in.
-
-and is licensed under the GPL version 3,
-see "/usr/share/common-licenses/GPL-3".
-
-# Please also look if there are files or directories which have a
-# different copyright/license attached and list them here.
diff --git a/debian/dirs b/debian/dirs
deleted file mode 100644
index d506f14..0000000
--- a/debian/dirs
+++ /dev/null
@@ -1,2 +0,0 @@
-etc
-var/lib/tomcat6/webapps/shim
diff --git a/debian/docs b/debian/docs
deleted file mode 100644
index fc82724..0000000
--- a/debian/docs
+++ /dev/null
@@ -1,2 +0,0 @@
-README
-ChangeLog
diff --git a/debian/get-orig-source b/debian/get-orig-source
deleted file mode 100755
index 51d43bf..0000000
--- a/debian/get-orig-source
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/sh -e
-
-COMPRESS=xz
-
-NAME=`dpkg-parsechangelog | awk '/^Source/ { print $2 }'`
-MVERSION=`dpkg-parsechangelog | awk '/^Version:/ { print $2 }' | sed 's/^\([0-9\.]\+\)[+~][-0-9]\+$/\1/'`
-
-mkdir -p ../tarballs
-cd ../tarballs
-# need to clean up the tarballs dir first because upstream tarball might
-# contain a directory with unpredictable name
-rm -rf *
-git clone --quiet https://github.com/freemed/freeshim
-cd $NAME
-VERSION=${MVERSION}+`date -d @$(git show --format="%at" | head -n1) +%Y%m%d`
-# for esthetical reasons set file timestamps (if git-restore-mtime is installed)
-git restore-mtime || true
-cd ..
-TARDIR=${NAME}-${VERSION}
-mv ${NAME} ${TARDIR}
-rm -rf ${TARDIR}/.git
-rm -f ${TARDIR}/jars/*
-
-GZIP="--best --no-name" tar --owner=root --group=root --mode=a+rX -caf "$NAME"_"$VERSION".orig.tar.${COMPRESS} "${TARDIR}"
-rm -rf ${TARDIR}
diff --git a/debian/maven.cleanIgnoreRules b/debian/maven.cleanIgnoreRules
deleted file mode 100644
index b47b61d..0000000
--- a/debian/maven.cleanIgnoreRules
+++ /dev/null
@@ -1,17 +0,0 @@
-# Maven clean ignore rules - ignore some Maven dependencies and plugins
-# during the clean phase of a Maven build
-# Format of this file is:
-# [group] [artifact] [type] [version] [classifier] [scope]
-# where each element can be either
-# - the exact string, for example org.apache for the group, or 3.1
-#   for the version. In this case, the element is simply matched
-#   and left as it is
-# - * (the star character, alone). In this case, anything will
-#   match and be left as it is. For example, using * on the
-#  position of the artifact field will match any artifact id
-# All elements much match before a rule can be applied
-# Example rule: match jar with groupid= junit, artifactid= junit
-# and version starting with 3., this dependency is then removed
-# from the POM before mvn clean is called
-#   junit junit jar s/3\\..*/3.x/
-
diff --git a/debian/maven.ignoreRules b/debian/maven.ignoreRules
deleted file mode 100644
index 0088a40..0000000
--- a/debian/maven.ignoreRules
+++ /dev/null
@@ -1,16 +0,0 @@
-# Maven ignore rules - ignore some Maven dependencies and plugins
-# Format of this file is:
-# [group] [artifact] [type] [version] [classifier] [scope]
-# where each element can be either
-# - the exact string, for example org.apache for the group, or 3.1
-#   for the version. In this case, the element is simply matched
-#   and left as it is
-# - * (the star character, alone). In this case, anything will
-#   match and be left as it is. For example, using * on the
-#  position of the artifact field will match any artifact id
-# All elements much match before a rule can be applied
-# Example rule: match jar with groupid= junit, artifactid= junit
-# and version starting with 3., this dependency is then removed
-# from the POM
-#   junit junit jar s/3\\..*/3.x/
-
diff --git a/debian/maven.publishedRules b/debian/maven.publishedRules
deleted file mode 100644
index 822f087..0000000
--- a/debian/maven.publishedRules
+++ /dev/null
@@ -1,19 +0,0 @@
-# Maven published rules - additional rules to publish, to help
-# the packaging work of Debian maintainers using mh_make
-# Format of this file is:
-# [group] [artifact] [type] [version] [classifier] [scope]
-# where each element can be either
-# - the exact string, for example org.apache for the group, or 3.1
-#   for the version. In this case, the element is simply matched
-#   and left as it is
-# - * (the star character, alone). In this case, anything will
-#   match and be left as it is. For example, using * on the
-#  position of the artifact field will match any artifact id
-# - a regular expression of the form s/match/replace/
-#   in this case, elements that match are transformed using
-#   the regex rule.
-# All elements much match before a rule can be applied
-# Example rule: match jar with groupid= junit, artifactid= junit
-# and version starting with 3., replacing the version with 3.x
-#   junit junit jar s/3\\..*/3.x/
-
diff --git a/debian/maven.rules b/debian/maven.rules
deleted file mode 100644
index a534606..0000000
--- a/debian/maven.rules
+++ /dev/null
@@ -1,21 +0,0 @@
-# Maven rules - transform Maven dependencies and plugins
-# Format of this file is:
-# [group] [artifact] [type] [version] [classifier] [scope]
-# where each element can be either
-# - the exact string, for example org.apache for the group, or 3.1
-#   for the version. In this case, the element is simply matched
-#   and left as it is
-# - * (the star character, alone). In this case, anything will
-#   match and be left as it is. For example, using * on the
-#  position of the artifact field will match any artifact id
-# - a regular expression of the form s/match/replace/
-#   in this case, elements that match are transformed using
-#   the regex rule.
-# All elements much match before a rule can be applied
-# Example rule: match jar with groupid= junit, artifactid= junit
-# and version starting with 3., replacing the version with 3.x
-#   junit junit jar s/3\\..*/3.x/
-
-junit junit jar s/4\..*/4.x/ * *
-log4j log4j jar s/1\.2\..*/1.2.x/ * *
-commons-logging s/commons-logging-api/commons-logging/ * s/.*/debian/ * *
diff --git a/debian/patches/no_maven-javadoc-plugin.patch b/debian/patches/no_maven-javadoc-plugin.patch
deleted file mode 100644
index 89468eb..0000000
--- a/debian/patches/no_maven-javadoc-plugin.patch
+++ /dev/null
@@ -1,222 +0,0 @@
---- shim-0.1.1.orig/shim-library/pom.xml
-+++ shim-0.1.1/shim-library/pom.xml
-@@ -69,19 +69,6 @@
- 		</dependency>
- 	</dependencies>
- 
--	<reporting>
--		<plugins>
--			<!-- Build javadocs for this project -->
--			<plugin>
--				<groupId>org.apache.maven.plugins</groupId>
--				<artifactId>maven-javadoc-plugin</artifactId>
--				<version>2.7</version>
--				<configuration>
--				</configuration>
--			</plugin>
--		</plugins>
--	</reporting>
--
- 	<build>
- 		<plugins>
- 			<!-- Compile -->
-@@ -95,14 +82,6 @@
- 				</configuration>
- 			</plugin>
- 
--			<!-- Build javadocs for this project -->
--			<plugin>
--				<groupId>org.apache.maven.plugins</groupId>
--				<artifactId>maven-javadoc-plugin</artifactId>
--				<version>2.7</version>
--				<configuration>
--				</configuration>
--			</plugin>
- 		</plugins>
- 	</build>
- 
---- shim-0.1.1.orig/shim-drivers/shim-driver-label-escpos/pom.xml
-+++ shim-0.1.1/shim-drivers/shim-driver-label-escpos/pom.xml
-@@ -52,19 +52,6 @@
- 		</dependency>
- 	</dependencies>
- 
--	<reporting>
--		<plugins>
--			<!-- Build javadocs for this project -->
--			<plugin>
--				<groupId>org.apache.maven.plugins</groupId>
--				<artifactId>maven-javadoc-plugin</artifactId>
--				<version>2.7</version>
--				<configuration>
--				</configuration>
--			</plugin>
--		</plugins>
--	</reporting>
--
- 	<build>
- 		<plugins>
- 			<plugin>
-@@ -77,14 +64,6 @@
- 				</configuration>
- 			</plugin>
- 
--			<!-- Build javadocs for this project -->
--			<plugin>
--				<groupId>org.apache.maven.plugins</groupId>
--				<artifactId>maven-javadoc-plugin</artifactId>
--				<version>2.7</version>
--				<configuration>
--				</configuration>
--			</plugin>
- 		</plugins>
- 	</build>
- 
---- shim-0.1.1.orig/shim-drivers/shim-driver-lab-microlab3500/pom.xml
-+++ shim-0.1.1/shim-drivers/shim-driver-lab-microlab3500/pom.xml
-@@ -46,19 +46,6 @@
- 		</dependency>
- 	</dependencies>
- 
--	<reporting>
--		<plugins>
--			<!-- Build javadocs for this project -->
--			<plugin>
--				<groupId>org.apache.maven.plugins</groupId>
--				<artifactId>maven-javadoc-plugin</artifactId>
--				<version>2.7</version>
--				<configuration>
--				</configuration>
--			</plugin>
--		</plugins>
--	</reporting>
--
- 	<build>
- 		<plugins>
- 			<plugin>
-@@ -71,14 +58,6 @@
- 				</configuration>
- 			</plugin>
- 
--			<!-- Build javadocs for this project -->
--			<plugin>
--				<groupId>org.apache.maven.plugins</groupId>
--				<artifactId>maven-javadoc-plugin</artifactId>
--				<version>2.7</version>
--				<configuration>
--				</configuration>
--			</plugin>
- 		</plugins>
- 	</build>
- 
---- shim-0.1.1.orig/shim-drivers/shim-driver-dosing-scilog/pom.xml
-+++ shim-0.1.1/shim-drivers/shim-driver-dosing-scilog/pom.xml
-@@ -46,19 +46,6 @@
- 		</dependency>
- 	</dependencies>
- 
--	<reporting>
--		<plugins>
--			<!-- Build javadocs for this project -->
--			<plugin>
--				<groupId>org.apache.maven.plugins</groupId>
--				<artifactId>maven-javadoc-plugin</artifactId>
--				<version>2.7</version>
--				<configuration>
--				</configuration>
--			</plugin>
--		</plugins>
--	</reporting>
--
- 	<build>
- 		<plugins>
- 			<plugin>
-@@ -71,14 +58,6 @@
- 				</configuration>
- 			</plugin>
- 
--			<!-- Build javadocs for this project -->
--			<plugin>
--				<groupId>org.apache.maven.plugins</groupId>
--				<artifactId>maven-javadoc-plugin</artifactId>
--				<version>2.7</version>
--				<configuration>
--				</configuration>
--			</plugin>
- 		</plugins>
- 	</build>
- 
---- shim-0.1.1.orig/shim-drivers/shim-driver-signature-dummy/pom.xml
-+++ shim-0.1.1/shim-drivers/shim-driver-signature-dummy/pom.xml
-@@ -38,19 +38,6 @@
- 		</dependency>
- 	</dependencies>
- 
--	<reporting>
--		<plugins>
--			<!-- Build javadocs for this project -->
--			<plugin>
--				<groupId>org.apache.maven.plugins</groupId>
--				<artifactId>maven-javadoc-plugin</artifactId>
--				<version>2.7</version>
--				<configuration>
--				</configuration>
--			</plugin>
--		</plugins>
--	</reporting>
--
- 	<build>
- 		<plugins>
- 			<plugin>
-@@ -63,14 +50,6 @@
- 				</configuration>
- 			</plugin>
- 
--			<!-- Build javadocs for this project -->
--			<plugin>
--				<groupId>org.apache.maven.plugins</groupId>
--				<artifactId>maven-javadoc-plugin</artifactId>
--				<version>2.7</version>
--				<configuration>
--				</configuration>
--			</plugin>
- 		</plugins>
- 	</build>
- 
---- shim-0.1.1.orig/shim-drivers/shim-driver-lab-clinitek50/pom.xml
-+++ shim-0.1.1/shim-drivers/shim-driver-lab-clinitek50/pom.xml
-@@ -46,19 +46,6 @@
- 		</dependency>
- 	</dependencies>
- 
--	<reporting>
--		<plugins>
--			<!-- Build javadocs for this project -->
--			<plugin>
--				<groupId>org.apache.maven.plugins</groupId>
--				<artifactId>maven-javadoc-plugin</artifactId>
--				<version>2.7</version>
--				<configuration>
--				</configuration>
--			</plugin>
--		</plugins>
--	</reporting>
--
- 	<build>
- 		<plugins>
- 			<plugin>
-@@ -71,14 +58,6 @@
- 				</configuration>
- 			</plugin>
- 
--			<!-- Build javadocs for this project -->
--			<plugin>
--				<groupId>org.apache.maven.plugins</groupId>
--				<artifactId>maven-javadoc-plugin</artifactId>
--				<version>2.7</version>
--				<configuration>
--				</configuration>
--			</plugin>
- 		</plugins>
- 	</build>
- 
diff --git a/debian/patches/series b/debian/patches/series
deleted file mode 100644
index e1269b7..0000000
--- a/debian/patches/series
+++ /dev/null
@@ -1,2 +0,0 @@
-use_debian_maven_settings.patch
-no_maven-javadoc-plugin.patch
diff --git a/debian/patches/use_debian_maven_settings.patch b/debian/patches/use_debian_maven_settings.patch
deleted file mode 100644
index 2148b77..0000000
--- a/debian/patches/use_debian_maven_settings.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- shim-0.1.1.orig/shim-library/install-deps.sh
-+++ shim-0.1.1/shim-library/install-deps.sh
-@@ -21,7 +21,7 @@
- # along with this program; if not, write to the Free Software
- # Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
- 
--mvn install:install-file -DgroupId=org.rxtx -DartifactId=rxtx -Dversion=2.2pre2 -Dpackaging=jar -Dfile=deps/rxtx-2.2pre2.jar
-+mvn -s ../debian/maven-settings.xml install:install-file -DgroupId=org.rxtx -DartifactId=rxtx -Dversion=2.2pre2 -Dpackaging=jar -Dfile=deps/rxtx-2.2pre2.jar
- 
- #mvn install:install-file -DgroupId=net.sf.extcos -DartifactId=extcos -Dversion=0.1.1b -Dpackaging=jar -Dfile=deps/extcos-0.1.1b.jar
- 
diff --git a/debian/rules b/debian/rules
deleted file mode 100755
index 7282961..0000000
--- a/debian/rules
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/make -f
-
-include /usr/share/cdbs/1/rules/debhelper.mk
-include /usr/share/cdbs/1/class/maven.mk
-
-JAVA_HOME := /usr/lib/jvm/default-java
-DEB_MAVEN_DOC_TARGET := javadoc:jar javadoc:aggregate
-
diff --git a/debian/shim.poms b/debian/shim.poms
deleted file mode 100644
index 31e2bdf..0000000
--- a/debian/shim.poms
+++ /dev/null
@@ -1,34 +0,0 @@
-# List of POM files for the package
-# Format of this file is:
-# <path to pom file> [option]*
-# where option can be:
-#   --ignore: ignore this POM or
-#   --no-parent: remove the <parent> tag from the POM
-#   --package=<package>: an alternative package to use when installing this POM
-#      and its artifact
-#   --has-package-version: to indicate that the original version of the POM is the same as the upstream part
-#      of the version for the package.
-#   --keep-elements=<elem1,elem2>: a list of XML elements to keep in the POM
-#      during a clean operation with mh_cleanpom or mh_installpom
-#   --artifact=<path>: path to the build artifact associated with this POM,
-#      it will be installed when using the command mh_install
-#   --java-lib: install the jar into /usr/share/java to comply with Debian
-#      packaging guidelines
-#   --usj-name=<name>: name to use when installing the library in /usr/share/java
-#   --usj-version=<version>: version to use when installing the library in /usr/share/java
-#   --no-usj-versionless: don't install the versionless link in /usr/share/java
-#   --dest-jar=<path>: the destination for the real jar
-#   it will be installed with mh_install.
-#   --classifier=<classifier>: Optional, the classifier for the jar. Empty by default.
-#   --ignore-pom: don't install the POM with mh_install or mh_installpoms. To use with POM files that are created
-#     temporarily for certain artifacts such as Javadoc jars.
-#
-pom.xml
-shim-library/pom.xml
-shim-drivers/pom.xml
-shim-drivers/shim-driver-lab-clinitek50/pom.xml
-shim-drivers/shim-driver-lab-microlab3500/pom.xml
-shim-drivers/shim-driver-label-escpos/pom.xml
-shim-drivers/shim-driver-signature-dummy/pom.xml
-shim-drivers/shim-driver-dosing-scilog/pom.xml
-shim-webapp/pom.xml
diff --git a/debian/source/format b/debian/source/format
deleted file mode 100644
index 163aaf8..0000000
--- a/debian/source/format
+++ /dev/null
@@ -1 +0,0 @@
-3.0 (quilt)
diff --git a/git2cl b/git2cl
new file mode 100755
index 0000000..1c2ab3f
--- /dev/null
+++ b/git2cl
@@ -0,0 +1,372 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2007, 2008 Simon Josefsson <simon at josefsson.org>
+# Copyright (C) 2007 Luis Mondesi <lemsx1 at gmail.com>
+# * calls git directly. To use it just: 
+#   cd ~/Project/my_git_repo; git2cl > ChangeLog
+# * implements strptime()
+# * fixes bugs in $comment parsing
+#   - copy input before we remove leading spaces
+#   - skip "merge branch" statements as they don't
+#     have information about files (i.e. we never
+#     go into $state 2)
+#   - behaves like a pipe/filter if input is given from the CLI
+#     else it calls git log by itself
+#
+# The functions mywrap, last_line_len, wrap_log_entry are derived from
+# the cvs2cl tool, see <http://www.red-bean.com/cvs2cl/>:
+# Copyright (C) 2001,2002,2003,2004 Martyn J. Pearce <fluffy at cpan.org>
+# Copyright (C) 1999 Karl Fogel <kfogel at red-bean.com>
+#
+# git2cl is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# git2cl is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with git2cl; see the file COPYING.  If not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+use strict;
+use POSIX qw(strftime);
+use Text::Wrap qw(wrap);
+use FileHandle;
+
+use constant EMPTY_LOG_MESSAGE => '*** empty log message ***';
+
+# this is a helper hash for stptime.
+# Assumes you are calling 'git log ...' with LC_ALL=C
+my %month = (
+    'Jan'=>0,
+    'Feb'=>1,
+    'Mar'=>2,
+    'Apr'=>3,
+    'May'=>4,
+    'Jun'=>5,
+    'Jul'=>6,
+    'Aug'=>7,
+    'Sep'=>8,
+    'Oct'=>9,
+    'Nov'=>10,
+    'Dec'=>11,
+);
+
+my $fh = new FileHandle;
+
+sub key_ready
+{
+    my ($rin, $nfd);
+    vec($rin, fileno(STDIN), 1) = 1;
+    return $nfd = select($rin, undef, undef, 0);
+}
+
+sub strptime {
+    my $str = shift;
+    return undef if not defined $str;
+
+    # we are parsing this format
+    # Fri Oct 26 00:42:56 2007 -0400
+    # to these fields
+    # sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1
+    # Luis Mondesi <lemsx1 at gmail.com>
+    my @date;
+    if ($str =~ /([[:alpha:]]{3})\s+([[:alpha:]]{3})\s+([[:digit:]]{1,2})\s+([[:digit:]]{1,2}):([[:digit:]]{1,2}):([[:digit:]]{1,2})\s+([[:digit:]]{4})/){
+        push(@date,$6,$5,$4,$3,$month{$2},($7 - 1900),-1,-1,-1);
+    } else {
+        die ("Cannot parse date '$str'\n'");
+    }
+    return @date;
+}
+
+sub mywrap {
+    my ($indent1, $indent2, @text) = @_;
+    # If incoming text looks preformatted, don't get clever
+    my $text = Text::Wrap::wrap($indent1, $indent2, @text);
+    if ( grep /^\s+/m, @text ) {
+	return $text;
+    }
+    my @lines = split /\n/, $text;
+    $indent2 =~ s!^((?: {8})+)!"\t" x (length($1)/8)!e;
+    $lines[0] =~ s/^$indent1\s+/$indent1/;
+    s/^$indent2\s+/$indent2/
+	for @lines[1..$#lines];
+    my $newtext = join "\n", @lines;
+    $newtext .= "\n"
+	if substr($text, -1) eq "\n";
+    return $newtext;
+}
+
+sub last_line_len {
+    my $files_list = shift;
+    my @lines = split (/\n/, $files_list);
+    my $last_line = pop (@lines);
+    return length ($last_line);
+}
+
+# A custom wrap function, sensitive to some common constructs used in
+# log entries.
+sub wrap_log_entry {
+    my $text = shift;                  # The text to wrap.
+    my $left_pad_str = shift;          # String to pad with on the left.
+
+    # These do NOT take left_pad_str into account:
+    my $length_remaining = shift;      # Amount left on current line.
+    my $max_line_length  = shift;      # Amount left for a blank line.
+
+    my $wrapped_text = '';             # The accumulating wrapped entry.
+    my $user_indent = '';              # Inherited user_indent from prev line.
+
+    my $first_time = 1;                # First iteration of the loop?
+    my $suppress_line_start_match = 0; # Set to disable line start checks.
+
+    my @lines = split (/\n/, $text);
+    while (@lines)   # Don't use `foreach' here, it won't work.
+    {
+	my $this_line = shift (@lines);
+	chomp $this_line;
+
+	if ($this_line =~ /^(\s+)/) {
+	    $user_indent = $1;
+	}
+	else {
+	    $user_indent = '';
+	}
+
+	# If it matches any of the line-start regexps, print a newline now...
+	if ($suppress_line_start_match)
+	{
+	    $suppress_line_start_match = 0;
+	}
+	elsif (($this_line =~ /^(\s*)\*\s+[a-zA-Z0-9]/)
+	       || ($this_line =~ /^(\s*)\* [a-zA-Z0-9_\.\/\+-]+/)
+	       || ($this_line =~ /^(\s*)\([a-zA-Z0-9_\.\/\+-]+(\)|,\s*)/)
+	       || ($this_line =~ /^(\s+)(\S+)/)
+	       || ($this_line =~ /^(\s*)- +/)
+	       || ($this_line =~ /^()\s*$/)
+	       || ($this_line =~ /^(\s*)\*\) +/)
+	       || ($this_line =~ /^(\s*)[a-zA-Z0-9](\)|\.|\:) +/))
+	{
+	    $length_remaining = $max_line_length - (length ($user_indent));
+	}
+
+	# Now that any user_indent has been preserved, strip off leading
+	# whitespace, so up-folding has no ugly side-effects.
+	$this_line =~ s/^\s*//;
+
+	# Accumulate the line, and adjust parameters for next line.
+	my $this_len = length ($this_line);
+	if ($this_len == 0)
+	{
+	    # Blank lines should cancel any user_indent level.
+	    $user_indent = '';
+	    $length_remaining = $max_line_length;
+	}
+	elsif ($this_len >= $length_remaining) # Line too long, try breaking it.
+	{
+	    # Walk backwards from the end.  At first acceptable spot, break
+	    # a new line.
+	    my $idx = $length_remaining - 1;
+	    if ($idx < 0) { $idx = 0 };
+	    while ($idx > 0)
+	    {
+		if (substr ($this_line, $idx, 1) =~ /\s/)
+		{
+		    my $line_now = substr ($this_line, 0, $idx);
+		    my $next_line = substr ($this_line, $idx);
+		    $this_line = $line_now;
+
+		    # Clean whitespace off the end.
+		    chomp $this_line;
+
+		    # The current line is ready to be printed.
+		    $this_line .= "\n${left_pad_str}";
+
+		    # Make sure the next line is allowed full room.
+		    $length_remaining = $max_line_length - (length ($user_indent));
+
+		    # Strip next_line, but then preserve any user_indent.
+		    $next_line =~ s/^\s*//;
+
+		    # Sneak a peek at the user_indent of the upcoming line, so
+		    # $next_line (which will now precede it) can inherit that
+		    # indent level.  Otherwise, use whatever user_indent level
+		    # we currently have, which might be none.
+		    my $next_next_line = shift (@lines);
+		    if ((defined ($next_next_line)) && ($next_next_line =~ /^(\s+)/)) {
+			$next_line = $1 . $next_line if (defined ($1));
+			# $length_remaining = $max_line_length - (length ($1));
+			$next_next_line =~ s/^\s*//;
+		    }
+		    else {
+			$next_line = $user_indent . $next_line;
+		    }
+		    if (defined ($next_next_line)) {
+			unshift (@lines, $next_next_line);
+		    }
+		    unshift (@lines, $next_line);
+
+		    # Our new next line might, coincidentally, begin with one of
+		    # the line-start regexps, so we temporarily turn off
+		    # sensitivity to that until we're past the line.
+		    $suppress_line_start_match = 1;
+
+		    last;
+		}
+		else
+		{
+		    $idx--;
+		}
+	    }
+
+	    if ($idx == 0)
+	    {
+		# We bottomed out because the line is longer than the
+		# available space.  But that could be because the space is
+		# small, or because the line is longer than even the maximum
+		# possible space.  Handle both cases below.
+
+		if ($length_remaining == ($max_line_length - (length ($user_indent))))
+		{
+		    # The line is simply too long -- there is no hope of ever
+		    # breaking it nicely, so just insert it verbatim, with
+		    # appropriate padding.
+		    $this_line = "\n${left_pad_str}${this_line}";
+		}
+		else
+		{
+		    # Can't break it here, but may be able to on the next round...
+		    unshift (@lines, $this_line);
+		    $length_remaining = $max_line_length - (length ($user_indent));
+		    $this_line = "\n${left_pad_str}";
+		}
+	    }
+	}
+	else  # $this_len < $length_remaining, so tack on what we can.
+	{
+	    # Leave a note for the next iteration.
+	    $length_remaining = $length_remaining - $this_len;
+
+	    if ($this_line =~ /\.$/)
+	    {
+		$this_line .= "  ";
+		$length_remaining -= 2;
+	    }
+	    else  # not a sentence end
+	    {
+		$this_line .= " ";
+		$length_remaining -= 1;
+	    }
+	}
+
+	# Unconditionally indicate that loop has run at least once.
+	$first_time = 0;
+
+	$wrapped_text .= "${user_indent}${this_line}";
+    }
+
+    # One last bit of padding.
+    $wrapped_text .= "\n";
+
+    return $wrapped_text;
+}
+
+# main
+
+my @date;
+my $author;
+my @files;
+my $comment;
+
+my $state; # 0-header 1-comment 2-files
+my $done = 0;
+
+$state = 0;
+
+# if reading from STDIN, we assume that we are
+# getting git log as input
+if (key_ready())
+{
+
+    #my $dummyfh; # don't care about writing
+    #($fh,$dummyfh) = FileHandle::pipe;
+    $fh->fdopen(*STDIN, 'r');
+}
+else
+{
+    $fh->open("LC_ALL=C git log --pretty --numstat --summary|")
+	or die("Cannot execute git log...$!\n");
+}
+
+while (my $_l = <$fh>) {
+    #print STDERR "debug ($state, " . (@date ? (strftime "%Y-%m-%d", @date) : "") . "): `$_'\n";
+    if ($state == 0) {
+	if ($_l =~ m,^Author: (.*),) {
+	    $author = $1;
+	}
+	if ($_l =~ m,^Date: (.*),) {
+	    @date = strptime($1);
+	}
+	$state = 1 if ($_l =~ m,^$, and $author and (@date+0>0));
+    } elsif ($state == 1) {
+        # * modifying our input text is a bad choice
+        #   let's make a copy of it first, then we remove spaces 
+        # * if we meet a "merge branch" statement, we need to start
+        #   over and find a real entry
+        # Luis Mondesi <lemsx1 at gmail.com>
+        my $_s = $_l;
+	$_s =~ s/^    //g;
+        if ($_s =~ m/^Merge branch/)
+        {
+            $state=0;
+            next;
+        }
+	$comment = $comment . $_s;
+	$state = 2 if ($_l =~ m,^$,);
+    } elsif ($state == 2) {
+	if ($_l =~ m,^([0-9]+)\t([0-9]+)\t(.*)$,) {
+	    push @files, $3;
+	}
+	$done = 1 if ($_l =~ m,^$,);
+    }
+
+    if ($done) {
+	print (strftime "%Y-%m-%d  $author\n\n", @date);
+
+	my $files = join (", ", @files);
+	$files = mywrap ("\t", "\t", "* $files"), ": ";
+
+	if (index($comment, EMPTY_LOG_MESSAGE) > -1 ) {
+	    $comment = "[no log message]\n";
+	}
+
+	my $files_last_line_len = 0;
+	$files_last_line_len = last_line_len($files) + 1;
+	my $msg = wrap_log_entry($comment, "\t", 69-$files_last_line_len, 69);
+
+	$msg =~ s/[ \t]+\n/\n/g;
+
+	print "$files: $msg\n";
+
+	@date = ();
+	$author = "";
+	@files = ();
+	$comment = "";
+
+	$state = 0;
+	$done = 0;
+    }
+}
+
+if (@date + 0)
+{
+    print (strftime "%Y-%m-%d  $author\n\n", @date);
+    my $msg = wrap_log_entry($comment, "\t", 69, 69);
+    $msg =~ s/[ \t]+\n/\n/g;
+    print "\t* $msg\n";
+}
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..20ca6bd
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,42 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+                      http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.freemedsoftware</groupId>
+  <artifactId>shim</artifactId>
+  <name>shim</name>
+  <version>0.1.1</version>
+  <packaging>pom</packaging>
+  <modules>
+    <module>shim-library</module>
+    <module>shim-drivers</module>
+    <module>shim-webapp</module>
+  </modules>
+  <build>
+    <defaultGoal>package</defaultGoal>
+    <plugins>
+      <plugin>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <version>2.2.1</version>
+        <configuration>
+          <descriptors>
+            <descriptor>assembly/dist.xml</descriptor>
+          </descriptors>
+          <finalName>shim</finalName>
+          <outputDirectory>.</outputDirectory>
+          <workDirectory>target/assembly/work</workDirectory>
+        </configuration>
+        <executions>
+          <execution>
+            <id>make-assembly</id>
+            <phase>package</phase>
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+     </plugins>
+  </build>
+</project>
diff --git a/project.properties b/project.properties
new file mode 100644
index 0000000..2176657
--- /dev/null
+++ b/project.properties
@@ -0,0 +1 @@
+shim.version=0.1.1
diff --git a/remove-nonfree.xsl b/remove-nonfree.xsl
new file mode 100644
index 0000000..2f9566f
--- /dev/null
+++ b/remove-nonfree.xsl
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<!--
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:pom="http://maven.apache.org/POM/4.0.0" version="1.0" >
+
+  <xsl:output method="xml" indent="yes"/> 
+
+  <!-- Remove non-free Topaz stuff -->
+
+  <xsl:template match="pom:module[text()='shim-driver-signature-topaz']"></xsl:template>
+  <xsl:template match="pom:dependency[pom:groupId='org.freemedsoftware' and pom:artifactId='shim-driver-signature-topaz']"></xsl:template>
+ 
+  <xsl:template match="comment()">
+    <xsl:comment><xsl:value-of select="."/></xsl:comment>
+  </xsl:template>
+ 
+  <xsl:template match="*">
+    <xsl:copy><xsl:apply-templates/></xsl:copy>
+  </xsl:template>
+ 
+</xsl:stylesheet>
+
diff --git a/shim-drivers/.project b/shim-drivers/.project
new file mode 100644
index 0000000..484bb3c
--- /dev/null
+++ b/shim-drivers/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>shim-drivers</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/shim-drivers/.settings/org.maven.ide.eclipse.prefs b/shim-drivers/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..ec8e7f7
--- /dev/null
+++ b/shim-drivers/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Fri Jul 30 13:06:04 EDT 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/shim-drivers/README b/shim-drivers/README
new file mode 100644
index 0000000..ff1d9b9
--- /dev/null
+++ b/shim-drivers/README
@@ -0,0 +1,5 @@
+$Id$
+
+All third party drivers for SHIM devices should go in here. The API is
+defined in the shim-library codebase.
+
diff --git a/shim-drivers/pom.xml b/shim-drivers/pom.xml
new file mode 100644
index 0000000..708f08b
--- /dev/null
+++ b/shim-drivers/pom.xml
@@ -0,0 +1,26 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+                      http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.freemedsoftware</groupId>
+  <artifactId>shim-drivers</artifactId>
+  <name>shim-drivers</name>
+  <version>0.1.1</version>
+  <packaging>pom</packaging>
+  <modules>
+    <module>shim-driver-lab-clinitek50</module>
+    <module>shim-driver-lab-microlab3500</module>
+    <module>shim-driver-label-escpos</module>
+    <module>shim-driver-signature-dummy</module>
+    <module>shim-driver-signature-topaz</module>
+    <module>shim-driver-dosing-scilog</module>
+  </modules>
+  <dependencies>
+    <dependency>
+      <groupId>org.freemedsoftware</groupId>
+      <artifactId>shim-library</artifactId>
+      <version>${version}</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/shim-drivers/shim-driver-dosing-scilog/.classpath b/shim-drivers/shim-driver-dosing-scilog/.classpath
new file mode 100644
index 0000000..5d96226
--- /dev/null
+++ b/shim-drivers/shim-driver-dosing-scilog/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/shim-drivers/shim-driver-dosing-scilog/.project b/shim-drivers/shim-driver-dosing-scilog/.project
new file mode 100644
index 0000000..a4ca121
--- /dev/null
+++ b/shim-drivers/shim-driver-dosing-scilog/.project
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>shim-driver-dosing-scilog</name>
+	<comment>NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse.</comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+	</natures>
+</projectDescription>
diff --git a/shim-drivers/shim-driver-dosing-scilog/.settings/org.eclipse.jdt.core.prefs b/shim-drivers/shim-driver-dosing-scilog/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..52cd2f2
--- /dev/null
+++ b/shim-drivers/shim-driver-dosing-scilog/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+#Fri Aug 13 15:44:58 EDT 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/shim-drivers/shim-driver-dosing-scilog/.settings/org.eclipse.wst.common.component b/shim-drivers/shim-driver-dosing-scilog/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..8fab493
--- /dev/null
+++ b/shim-drivers/shim-driver-dosing-scilog/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="shim-driver-signature-dummy">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+    </wb-module>
+</project-modules>
diff --git a/shim-drivers/shim-driver-dosing-scilog/.settings/org.eclipse.wst.common.project.facet.core.xml b/shim-drivers/shim-driver-dosing-scilog/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..f68988c
--- /dev/null
+++ b/shim-drivers/shim-driver-dosing-scilog/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="jst.java" version="6.0"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/shim-drivers/shim-driver-dosing-scilog/.settings/org.maven.ide.eclipse.prefs b/shim-drivers/shim-driver-dosing-scilog/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..ec8e7f7
--- /dev/null
+++ b/shim-drivers/shim-driver-dosing-scilog/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Fri Jul 30 13:06:04 EDT 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/shim-drivers/shim-driver-dosing-scilog/pom.xml b/shim-drivers/shim-driver-dosing-scilog/pom.xml
new file mode 100644
index 0000000..35b0499
--- /dev/null
+++ b/shim-drivers/shim-driver-dosing-scilog/pom.xml
@@ -0,0 +1,86 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<groupId>org.freemedsoftware</groupId>
+	<artifactId>shim-driver-dosing-scilog</artifactId>
+	<version>0.1.1</version>
+	<packaging>jar</packaging>
+
+	<name>shim-driver-dosing-scilog</name>
+	<url>http://freemedsoftware.org</url>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+	</properties>
+
+	<dependencies>
+
+		<dependency>
+			<groupId>org.freemedsoftware</groupId>
+			<artifactId>shim-library</artifactId>
+			<version>${version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.rxtx</groupId>
+			<artifactId>rxtx</artifactId>
+			<version>2.2pre2</version>
+			<type>jar</type>
+			<scope>system</scope>
+      <systemPath>${basedir}/../../shim-library/deps/rxtx-2.2pre2.jar</systemPath>
+		</dependency>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.8.2</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>log4j</groupId>
+			<artifactId>log4j</artifactId>
+			<version>1.2.16</version>
+			<type>jar</type>
+			<scope>compile</scope>
+		</dependency>
+	</dependencies>
+
+	<reporting>
+		<plugins>
+			<!-- Build javadocs for this project -->
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+				<version>2.8</version>
+				<configuration>
+				</configuration>
+			</plugin>
+		</plugins>
+	</reporting>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>2.3.2</version>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+
+			<!-- Build javadocs for this project -->
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+				<version>2.8</version>
+				<configuration>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/shim-drivers/shim-driver-dosing-scilog/src/main/java/org/freemedsoftware/device/impl/DosingPumpScilogShim.java b/shim-drivers/shim-driver-dosing-scilog/src/main/java/org/freemedsoftware/device/impl/DosingPumpScilogShim.java
new file mode 100644
index 0000000..3db6e3b
--- /dev/null
+++ b/shim-drivers/shim-driver-dosing-scilog/src/main/java/org/freemedsoftware/device/impl/DosingPumpScilogShim.java
@@ -0,0 +1,121 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device.impl;
+
+import gnu.io.NoSuchPortException;
+import gnu.io.PortInUseException;
+import gnu.io.UnsupportedCommOperationException;
+
+import java.io.IOException;
+import java.util.Timer;
+
+import org.apache.log4j.Logger;
+import org.freemedsoftware.device.DeviceCapability;
+import org.freemedsoftware.device.DosingPumpSerialInterface;
+import org.freemedsoftware.device.JobStoreItem;
+import org.freemedsoftware.device.SerialInterface;
+import org.freemedsoftware.device.ShimDevice;
+
+ at ShimDevice(name = "Scilog Dosing Pump Shim", capability = DeviceCapability.DEVICE_DOSING_PUMP)
+public class DosingPumpScilogShim extends DosingPumpSerialInterface {
+
+	protected Logger log = Logger.getLogger(DosingPumpScilogShim.class);
+
+	protected Timer timer = new Timer();
+
+	protected Integer jobId = null;
+
+	protected JobStoreItem item = null;
+
+	public final static int PROCESSING_LENGTH = 5000;
+
+	public DosingPumpScilogShim() {
+		setConfigName("org.freemedsoftware.device.impl.DosingPumpScilogShim");
+	}
+
+	/**
+	 * Raw transport of commands to pump. Should not be called directly, but
+	 * should be used by internal commands.
+	 * 
+	 * @param cmd
+	 * @return
+	 * @throws IOException
+	 * @throws PortInUseException
+	 * @throws UnsupportedCommOperationException
+	 * @throws NoSuchPortException
+	 */
+	protected String sendCommandToPump(String cmd) throws IOException,
+			PortInUseException, UnsupportedCommOperationException,
+			NoSuchPortException {
+		if (cmd == null) {
+			log.error("Null cmd given!");
+			throw new IOException("Null cmd given!");
+		}
+		if (serialInterface == null) {
+			log.error("Serial interface not initialized!");
+			throw new IOException("Serial interface not initialized!");
+		}
+		log.info("command to pump is " + cmd);
+		serialInterface.write(cmd);
+
+		// Consume first line as response from pump
+		log.info("Reading response.");
+		String out = serialInterface.read().trim();
+		if (out.indexOf(SerialInterface.CR) != -1) {
+			return out.substring(0, out.indexOf(SerialInterface.CR)).trim();
+		} else if (out.indexOf(SerialInterface.LF) != -1) {
+			return out.substring(0, out.indexOf(SerialInterface.LF)).trim();
+		}
+		log.info("Returned " + out.trim());
+		return out.trim();
+	}
+
+	@Override
+	public String dispenseDose(Integer units) throws Exception {
+		return sendCommandToPump("V" + units.toString());
+	}
+
+	@Override
+	public String getPumpStatus() throws Exception {
+		return sendCommandToPump("S");
+	}
+
+	@Override
+	public String primePump() throws Exception {
+		sendCommandToPump("C"
+				+ (String) config
+						.get("org.freemedsoftware.device.impl.DosingPumpScilogShim.primePumpDuration"));
+		return sendCommandToPump("P");
+	}
+
+	@Override
+	public String reversePump() throws Exception {
+		sendCommandToPump("C"
+				+ (String) config
+						.get("org.freemedsoftware.device.impl.DosingPumpScilogShim.reversePumpDuration"));
+		return sendCommandToPump("E");
+	}
+
+}
diff --git a/shim-drivers/shim-driver-lab-clinitek50/.classpath b/shim-drivers/shim-driver-lab-clinitek50/.classpath
new file mode 100644
index 0000000..5b16c9e
--- /dev/null
+++ b/shim-drivers/shim-driver-lab-clinitek50/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/shim-library"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/shim-drivers/shim-driver-lab-clinitek50/.project b/shim-drivers/shim-driver-lab-clinitek50/.project
new file mode 100644
index 0000000..d35e97f
--- /dev/null
+++ b/shim-drivers/shim-driver-lab-clinitek50/.project
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>shim-driver-lab-clinitek50</name>
+	<comment>NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse.</comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+	</natures>
+</projectDescription>
diff --git a/shim-drivers/shim-driver-lab-clinitek50/.settings/org.eclipse.jdt.core.prefs b/shim-drivers/shim-driver-lab-clinitek50/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..52cd2f2
--- /dev/null
+++ b/shim-drivers/shim-driver-lab-clinitek50/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+#Fri Aug 13 15:44:58 EDT 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/shim-drivers/shim-driver-lab-clinitek50/.settings/org.eclipse.wst.common.component b/shim-drivers/shim-driver-lab-clinitek50/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..fc1dc77
--- /dev/null
+++ b/shim-drivers/shim-driver-lab-clinitek50/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="shim-driver-lab-clinitek50">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+    </wb-module>
+</project-modules>
diff --git a/shim-drivers/shim-driver-lab-clinitek50/.settings/org.eclipse.wst.common.project.facet.core.xml b/shim-drivers/shim-driver-lab-clinitek50/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..f68988c
--- /dev/null
+++ b/shim-drivers/shim-driver-lab-clinitek50/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="jst.java" version="6.0"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/shim-drivers/shim-driver-lab-clinitek50/.settings/org.maven.ide.eclipse.prefs b/shim-drivers/shim-driver-lab-clinitek50/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..ec8e7f7
--- /dev/null
+++ b/shim-drivers/shim-driver-lab-clinitek50/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Fri Jul 30 13:06:04 EDT 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/shim-drivers/shim-driver-lab-clinitek50/pom.xml b/shim-drivers/shim-driver-lab-clinitek50/pom.xml
new file mode 100644
index 0000000..88fbbc4
--- /dev/null
+++ b/shim-drivers/shim-driver-lab-clinitek50/pom.xml
@@ -0,0 +1,86 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<groupId>org.freemedsoftware</groupId>
+	<artifactId>shim-driver-lab-clinitek50</artifactId>
+	<version>0.1.1</version>
+	<packaging>jar</packaging>
+
+	<name>shim-driver-lab-clinitek50</name>
+	<url>http://freemedsoftware.org</url>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+	</properties>
+
+	<dependencies>
+
+		<dependency>
+			<groupId>org.freemedsoftware</groupId>
+			<artifactId>shim-library</artifactId>
+			<version>${version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.rxtx</groupId>
+			<artifactId>rxtx</artifactId>
+			<version>2.2pre2</version>
+			<type>jar</type>
+			<scope>system</scope>
+      <systemPath>${basedir}/../../shim-library/deps/rxtx-2.2pre2.jar</systemPath>
+		</dependency>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.8.2</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>log4j</groupId>
+			<artifactId>log4j</artifactId>
+			<version>1.2.16</version>
+			<type>jar</type>
+			<scope>compile</scope>
+		</dependency>
+	</dependencies>
+
+	<reporting>
+		<plugins>
+			<!-- Build javadocs for this project -->
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+				<version>2.8</version>
+				<configuration>
+				</configuration>
+			</plugin>
+		</plugins>
+	</reporting>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>2.3.2</version>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+
+			<!-- Build javadocs for this project -->
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+				<version>2.8</version>
+				<configuration>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/shim-drivers/shim-driver-lab-clinitek50/src/main/java/org/freemedsoftware/device/impl/LabClinitek50Shim.java b/shim-drivers/shim-driver-lab-clinitek50/src/main/java/org/freemedsoftware/device/impl/LabClinitek50Shim.java
new file mode 100644
index 0000000..5d57881
--- /dev/null
+++ b/shim-drivers/shim-driver-lab-clinitek50/src/main/java/org/freemedsoftware/device/impl/LabClinitek50Shim.java
@@ -0,0 +1,378 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.freemedsoftware.device.impl;
+
+import gnu.io.UnsupportedCommOperationException;
+
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Timer;
+
+import org.apache.log4j.Logger;
+import org.freemedsoftware.device.DeviceCapability;
+import org.freemedsoftware.device.JobStoreItem;
+import org.freemedsoftware.device.LabSerialInterface;
+import org.freemedsoftware.device.ShimDevice;
+
+ at ShimDevice(name = "Clinitek50 Lab Shim", capability = DeviceCapability.DEVICE_VITAL_SIGNS)
+public class LabClinitek50Shim extends LabSerialInterface {
+
+	protected Logger log = Logger.getLogger(LabClinitek50Shim.class);
+
+	protected Timer timer = new Timer();
+
+	protected Integer jobId = null;
+
+	protected JobStoreItem item = null;
+
+	protected class ClinitekPacket {
+		protected boolean success;
+		protected String data;
+
+		public ClinitekPacket(boolean success, String data) {
+			setSuccess(success);
+			setData(data);
+		}
+
+		public String getData() {
+			return data;
+		}
+
+		public void setData(String data) {
+			this.data = data;
+		}
+
+		public boolean getSuccess() {
+			return success;
+		}
+
+		public void setSuccess(boolean success) {
+			this.success = success;
+		}
+	}
+
+	// Constant declarations
+	public static String ETX = "\003";
+	public static String ENQ = "\005";
+	public static String CMD_REQ_ID = ENQ;
+	public static String ACK = "\006";
+	public static String CMD_ACK_PACKET = ACK;
+	public static String XON = "\021";
+	public static String DC1 = XON;
+	public static String DC2 = "\022";
+	// this is contrary to the specs which show DC2 and DC3 swapped around
+	public static String CMD_REQ_DATA = DC2;
+	public static String XOFF = "\023";
+	public static String DC3 = XOFF;
+	public static String NAK = "\025";
+	public static String CMD_NAK_PACKET = NAK;
+	public static String EOL = "\r\n";
+	public static String CRLF = EOL;
+	public static int TIMEOUT = 3000;
+	public static int MAX_PACKET_SIZE = 1024;
+	public static String PACKET_HEADER = "\002\r\n"; // STX CR LF
+	public static String DEV_ID = "6510";
+	public static String[] KNOWN_GOOD_REVS = new String[] { "  ", "A " };
+	public static String[] KNOWN_GOOD_SW_VERS = new String[] { "01.00", "01.02" };
+	public static String[] KNOWN_STIX_TYPES = new String[] { "MULTISTIX 10 SG" };
+	public static String DATE_FORMAT = "yyMMdd";
+	public static String TIME_FORMAT = "HHmm";
+	public static DateFormat timeFormat = new SimpleDateFormat(DATE_FORMAT
+			+ TIME_FORMAT);
+
+	public LabClinitek50Shim() {
+		setConfigName("org.freemedsoftware.device.impl.LabClinitek50Shim");
+	}
+
+	@Override
+	public void init() throws Exception {
+		// Run original init
+		super.init();
+
+		// DTR must be LOW according to specs,
+		// if physically connected and set to HIGH the
+		// device controller will enter programming mode
+		serialInterface.getSerialPort().setDTR(false);
+	}
+
+	protected String getRecord() {
+		// enable data transfer
+		try {
+			serialInterface.write(XON);
+		} catch (IOException e) {
+			log.error(e);
+		}
+
+		// request data
+		try {
+			serialInterface.write(CMD_REQ_DATA);
+		} catch (IOException e) {
+			log.error(e);
+		}
+		try {
+			Thread.sleep(250);
+		} catch (InterruptedException e) {
+			log.error(e);
+			return null;
+		}
+
+		// receive data
+		String packet = receivePacket();
+		if (packet == null) {
+			return null;
+		}
+		// if packet == -1:
+		// return -1
+		if (!verifyDataPacket(packet)) {
+			// NAK packet
+			try {
+				serialInterface.write(CMD_NAK_PACKET);
+			} catch (IOException e) {
+				log.error(e);
+			}
+			return null;
+		}
+		try {
+			serialInterface.write(CMD_ACK_PACKET);
+		} catch (IOException e) {
+			log.error(e);
+		}
+		return packet;
+	}
+
+	protected String receivePacket() {
+		// wait for ETX which is supposed to terminate all packets
+		ClinitekPacket packet = waitForStr(ETX, TIMEOUT, MAX_PACKET_SIZE);
+		if (!packet.getSuccess()) {
+			if (packet.getData().equals(NAK)) {
+				log.info("no more data in device");
+				return "";
+			} else {
+				log.error("receiving packet from device failed");
+				return null;
+			}
+		}
+		if (!verifyGenericPacketStructure(packet.getData())) {
+			// NAK packet
+			try {
+				serialInterface.write(CMD_NAK_PACKET);
+			} catch (IOException e) {
+				log.error(e);
+			}
+			return null;
+		}
+		return packet.getData();
+	}
+
+	protected boolean verifyGenericPacketStructure(String packet) {
+		// does it start with STX CR LF ?
+		if (packet.substring(0, 2) != PACKET_HEADER) {
+			log.error("packet does not start with STX CR LF");
+			log.debug(packet);
+			return false;
+		}
+		// does it have at least 5 lines ?
+		if (!(packet.split(EOL).length > 2)) {
+			log.error("packet does not have at least 5 lines");
+			log.debug(packet);
+			return false;
+		}
+		// does it have a valid checksum ?
+		String rxd_crc = "0x"
+				+ packet.substring(packet.length() - 4, packet.length() - 2)
+						.toLowerCase();
+		// TODO: check crc
+		// crc_val = reduce(lambda x, y: x + ord(y), tuple(packet[1:-3]), 0) &
+		// 255;
+		String crc_val = "";
+		String hex_str = ""; // hex(crc_val)[2:];
+		String calced_crc = "";
+		if (hex_str.length() == 1) {
+			calced_crc = "0x0" + hex_str;
+		} else {
+			calced_crc = "0x" + hex_str;
+			if (!calced_crc.equals(rxd_crc)) {
+				log.error("packet checksum error: received [" + rxd_crc
+						+ "] vs. calculated [" + calced_crc + "]");
+				log.debug(packet);
+				return false;
+			}
+		}
+		// seems valid
+		log.debug("generic packet structure is valid");
+		return true;
+	}
+
+	protected boolean verifyDetectPacket(String packet) {
+		String[] lines = packet.split(EOL);
+		// product ID: 6510 = Clinitek 50
+		String tmp = lines[0].substring(0, 3);
+		if (tmp != DEV_ID) {
+			log
+					.error("device does not seem to be a Clinitek 50, product ID is ["
+							+ tmp + "], expected [" + DEV_ID + "]");
+			for (String line : lines) {
+				log.debug(line);
+			}
+			return false;
+		}
+		// product revision
+		tmp = lines[1].substring(3, 5);
+		if (!Arrays.asList(KNOWN_GOOD_REVS).contains(tmp)) {
+			log.warn("product revision [" + tmp
+					+ "] untested, trying to continue anyways");
+		}
+		// software version
+		tmp = lines[1].substring(5, 10);
+		if (!Arrays.asList(KNOWN_GOOD_SW_VERS).contains(tmp)) {
+			log.warn("software version [" + tmp
+					+ "] untested, trying to continue anyways");
+		}
+		// date/time
+		Date nowTimestamp = new Date();
+		Date timestamp = null;
+		try {
+			timestamp = timeFormat.parse(lines[0].substring(11, 21));
+		} catch (ParseException e) {
+			log.error(e);
+		}
+		int age = 0;
+		if (timestamp != null) {
+			log.info("device timestamp: " + timestamp.toString());
+			log.info("system timestamp: " + new Date().toString());
+			long msAge = (nowTimestamp.getTime() - timestamp.getTime());
+			if (msAge != 0) {
+				age = (int) (msAge / (1000 * 60 * 60));
+			} else {
+				age = 0;
+			}
+		}
+
+		if (age > 6) {
+			log.error("device time is off by " + age
+					+ " hours, please correct that");
+			return false;
+		}
+
+		// language-unit profile
+		String[] languageUnit = lines[1].split(" - ");
+		String lang = languageUnit[0];
+		String units = languageUnit[1];
+		log.info("language: " + lang);
+		log.info("unit system: " + units);
+		// STIX type
+		String stix_type = lines[2].trim();
+		if (!Arrays.asList(KNOWN_STIX_TYPES).contains(stix_type)) {
+			log.error("don't know how to handle stix of type " + stix_type);
+			return false;
+		}
+		// seems valid
+		return true;
+	}
+
+	protected boolean verifyDataPacket(String packet) {
+		log.info("skipping verification of data packet");
+		// seems valid
+		return true;
+	}
+
+	protected ClinitekPacket waitForStr(String aString, int aTimeout,
+			int max_bytes) {
+		try {
+			serialInterface.getSerialPort().enableReceiveTimeout(aTimeout);
+		} catch (UnsupportedCommOperationException e) {
+			log.error(e);
+		}
+
+		if (aString == null) {
+			return new ClinitekPacket(true, null);
+		}
+		if (aString == "") {
+			return new ClinitekPacket(false, "");
+		}
+
+		if (max_bytes < aString.length()) {
+			max_bytes = aString.length() + 1;
+		}
+
+		String rxd = "";
+		int loop = 0;
+		int slice = 100;
+		// how many loops ?
+		int max_loops = Math.abs(aTimeout / slice);
+		// wait for data
+		while (loop < max_loops) {
+			loop += 1;
+			// something there
+			int ch = -1;
+			try {
+				ch = serialInterface.getInputStream().read();
+			} catch (IOException e) {
+				log.error(e);
+				return new ClinitekPacket(false, rxd);
+			}
+			if (ch != -1) {
+				// get all there is
+				while (ch != -1) {
+					rxd = rxd + ch;
+					// did this contain our expected string already ?
+					if (rxd.contains(aString)) {
+						return new ClinitekPacket(true, rxd);
+					}
+
+					// did we exceed our character buffer limit ?
+					// this stops runaway serial ports
+					if (rxd.length() >= max_bytes) {
+						log.error("exceeded maximum # of bytes (" + max_bytes
+								+ ") to receive");
+						return new ClinitekPacket(false, rxd);
+					}
+				}
+				// nothing there, wait a slice
+			} else {
+				if (rxd.length() >= max_bytes) {
+					log.error("exceeded maximum # of bytes to receive");
+					return new ClinitekPacket(false, rxd);
+				}
+				try {
+					Thread.sleep(slice);
+				} catch (InterruptedException e) {
+					log.error(e);
+					return new ClinitekPacket(false, rxd);
+				}
+			}
+		}
+
+		// hm, waited for aTimeout but expected string not received
+		log.warn("wait for [" + aString + "] timed out after " + aTimeout
+				+ " ms");
+		log.debug(rxd);
+		return new ClinitekPacket(false, rxd);
+	}
+}
diff --git a/shim-drivers/shim-driver-lab-microlab3500/.classpath b/shim-drivers/shim-driver-lab-microlab3500/.classpath
new file mode 100644
index 0000000..5b16c9e
--- /dev/null
+++ b/shim-drivers/shim-driver-lab-microlab3500/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/shim-library"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/shim-drivers/shim-driver-lab-microlab3500/.project b/shim-drivers/shim-driver-lab-microlab3500/.project
new file mode 100644
index 0000000..7778c71
--- /dev/null
+++ b/shim-drivers/shim-driver-lab-microlab3500/.project
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>shim-driver-lab-microlab3500</name>
+	<comment>NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse.</comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+	</natures>
+</projectDescription>
diff --git a/shim-drivers/shim-driver-lab-microlab3500/.settings/org.eclipse.jdt.core.prefs b/shim-drivers/shim-driver-lab-microlab3500/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..52cd2f2
--- /dev/null
+++ b/shim-drivers/shim-driver-lab-microlab3500/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+#Fri Aug 13 15:44:58 EDT 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/shim-drivers/shim-driver-lab-microlab3500/.settings/org.eclipse.wst.common.component b/shim-drivers/shim-driver-lab-microlab3500/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..e5eb027
--- /dev/null
+++ b/shim-drivers/shim-driver-lab-microlab3500/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="shim-driver-lab-microlab3500">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+    </wb-module>
+</project-modules>
diff --git a/shim-drivers/shim-driver-lab-microlab3500/.settings/org.eclipse.wst.common.project.facet.core.xml b/shim-drivers/shim-driver-lab-microlab3500/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..f68988c
--- /dev/null
+++ b/shim-drivers/shim-driver-lab-microlab3500/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="jst.java" version="6.0"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/shim-drivers/shim-driver-lab-microlab3500/.settings/org.maven.ide.eclipse.prefs b/shim-drivers/shim-driver-lab-microlab3500/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..ec8e7f7
--- /dev/null
+++ b/shim-drivers/shim-driver-lab-microlab3500/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Fri Jul 30 13:06:04 EDT 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/shim-drivers/shim-driver-lab-microlab3500/doc/SerialML3500.doc b/shim-drivers/shim-driver-lab-microlab3500/doc/SerialML3500.doc
new file mode 100644
index 0000000..cc312c2
Binary files /dev/null and b/shim-drivers/shim-driver-lab-microlab3500/doc/SerialML3500.doc differ
diff --git a/shim-drivers/shim-driver-lab-microlab3500/pom.xml b/shim-drivers/shim-driver-lab-microlab3500/pom.xml
new file mode 100644
index 0000000..852968f
--- /dev/null
+++ b/shim-drivers/shim-driver-lab-microlab3500/pom.xml
@@ -0,0 +1,86 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<groupId>org.freemedsoftware</groupId>
+	<artifactId>shim-driver-lab-microlab3500</artifactId>
+	<version>0.1.1</version>
+	<packaging>jar</packaging>
+
+	<name>shim-driver-lab-microlab3500</name>
+	<url>http://freemedsoftware.org</url>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+	</properties>
+
+	<dependencies>
+
+		<dependency>
+			<groupId>org.freemedsoftware</groupId>
+			<artifactId>shim-library</artifactId>
+			<version>${version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.rxtx</groupId>
+			<artifactId>rxtx</artifactId>
+			<version>2.2pre2</version>
+			<type>jar</type>
+			<scope>system</scope>
+      <systemPath>${basedir}/../../shim-library/deps/rxtx-2.2pre2.jar</systemPath>
+		</dependency>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.8.2</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>log4j</groupId>
+			<artifactId>log4j</artifactId>
+			<version>1.2.16</version>
+			<type>jar</type>
+			<scope>compile</scope>
+		</dependency>
+	</dependencies>
+
+	<reporting>
+		<plugins>
+			<!-- Build javadocs for this project -->
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+				<version>2.8</version>
+				<configuration>
+				</configuration>
+			</plugin>
+		</plugins>
+	</reporting>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>2.3.2</version>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+
+			<!-- Build javadocs for this project -->
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+				<version>2.8</version>
+				<configuration>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/shim-drivers/shim-driver-lab-microlab3500/src/main/java/org/freemedsoftware/device/impl/LabMicroLab3500Shim.java b/shim-drivers/shim-driver-lab-microlab3500/src/main/java/org/freemedsoftware/device/impl/LabMicroLab3500Shim.java
new file mode 100644
index 0000000..fa5def1
--- /dev/null
+++ b/shim-drivers/shim-driver-lab-microlab3500/src/main/java/org/freemedsoftware/device/impl/LabMicroLab3500Shim.java
@@ -0,0 +1,302 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.freemedsoftware.device.impl;
+
+import gnu.io.SerialPort;
+import gnu.io.SerialPortEvent;
+import gnu.io.SerialPortEventListener;
+
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.freemedsoftware.device.DeviceCapability;
+import org.freemedsoftware.device.LabSerialInterface;
+import org.freemedsoftware.device.ShimDevice;
+
+ at ShimDevice(name = "MicroLab 3500 Lab Shim", capability = DeviceCapability.DEVICE_VITAL_SIGNS)
+public class LabMicroLab3500Shim extends LabSerialInterface implements
+		SerialPortEventListener {
+
+	protected Logger log = Logger.getLogger(LabMicroLab3500Shim.class);
+
+	protected static final int ACK = '\373'; // FB hex
+	protected static final int NACK = '\004'; // 04 hex
+	protected static final String PACKET_HEADER = "\245\132"; // A5 5A hex
+
+	protected class TestResult {
+
+		private Map<String, Double> testValues = new HashMap<String, Double>();
+		private int testType;
+		private String patientId;
+		private Date testDate;
+
+		public void setTestValues(Map<String, Double> testValues) {
+			this.testValues = testValues;
+		}
+
+		public Map<String, Double> getTestValues() {
+			return testValues;
+		}
+
+		public void addTestValue(String test, Double value) {
+			getTestValues().put(test, value);
+		}
+
+		public void setTestType(int testType) {
+			this.testType = testType;
+		}
+
+		public int getTestType() {
+			return testType;
+		}
+
+		public void setPatientId(String patientId) {
+			this.patientId = patientId;
+		}
+
+		public String getPatientId() {
+			return patientId;
+		}
+
+		public void setTestDate(Date testDate) {
+			this.testDate = testDate;
+		}
+
+		public Date getTestDate() {
+			return testDate;
+		}
+	}
+
+	/**
+	 * Data packet encapsulation class, meant to hold a raw data packet.
+	 */
+	protected class DataPacket {
+
+		private int packetType;
+		private String data;
+
+		public void setPacketType(int packetType) {
+			this.packetType = packetType;
+		}
+
+		public int getPacketType() {
+			return packetType;
+		}
+
+		public void setData(String data) {
+			this.data = data;
+		}
+
+		public String getData() {
+			return data;
+		}
+	}
+
+	public LabMicroLab3500Shim() {
+		setConfigName("org.freemedsoftware.device.impl.LabMicroLab3500Shim");
+	}
+
+	@Override
+	public void init() throws Exception {
+		super.init();
+
+		// Force proper serial port config, since this is the only one that
+		// works properly with this particular piece of hardware.
+		serialInterface.getSerialPort().setSerialPortParams(4800,
+				SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
+				SerialPort.PARITY_NONE);
+
+		serialInterface.getSerialPort().addEventListener(this);
+	}
+
+	@Override
+	public void serialEvent(SerialPortEvent event) {
+		if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
+			log.info("SerialPortEvent.DATA_AVAILABLE");
+			try {
+				DataPacket packet = readDataPacket();
+				handleDataPacket(packet);
+			} catch (IOException e) {
+				log.error("Failure, sending NACK", e);
+				sendNack();
+			}
+		}
+	}
+
+	protected void handleDataPacket(DataPacket packet) {
+		log.info("handleDataPacket for type " + packet.getPacketType());
+		// TODO: handle different data packet types
+	}
+
+	/**
+	 * Read length bytes of data from the serial port.
+	 * 
+	 * @param length
+	 * @return
+	 * @throws IOException
+	 */
+	protected String readBytes(int length) throws IOException {
+		StringBuilder result = new StringBuilder();
+		StringBuilder debugResult = new StringBuilder();
+		for (int pos = 0; pos < length; pos++) {
+			int ch = serialInterface.getInputStream().read();
+			result.append((char) ch);
+			debugResult.append(" ").append(charToHex((char) ch));
+		}
+		log.debug("Received " + length + "bytes (" + debugResult.toString()
+				+ " )");
+		return result.toString();
+	}
+
+	/**
+	 * Send ACK packet to device.
+	 * 
+	 * @throws IOException
+	 */
+	protected void sendAck() throws IOException {
+		serialInterface.getOutputStream().write(ACK);
+	}
+
+	/**
+	 * Send NACK packet to device.
+	 */
+	protected void sendNack() {
+		try {
+			serialInterface.getOutputStream().write(NACK);
+		} catch (IOException e) {
+			log.error("Failed to send NACK", e);
+		}
+	}
+
+	/**
+	 * Read a <DataPacket> from the device.
+	 * 
+	 * @return
+	 * @throws IOException
+	 */
+	protected DataPacket readDataPacket() throws IOException {
+		// Read two bytes of data
+		String ack = readBytes(2);
+		if (!ack.contentEquals(PACKET_HEADER)) {
+			throw new IOException("Invalid packet header");
+		}
+		// Content length is two bytes, n + 1
+		String contentLengthString = readBytes(2);
+		int contentLength = ((int) contentLengthString.charAt(0) * 256)
+				+ ((int) contentLengthString.charAt(1)) - 1;
+
+		// Packet type is one byte
+		int packetType = serialInterface.getInputStream().read();
+
+		String content = readBytes(contentLength);
+
+		// TODO: check checksum
+		int checksumByte = serialInterface.getInputStream().read();
+
+		// Form data packet to send back
+		DataPacket packet = new DataPacket();
+		packet.setPacketType(packetType);
+		packet.setData(content);
+
+		// Send an acknowledgement if we've gotten this far without throwing an
+		// exception.
+		sendAck();
+
+		return packet;
+	}
+
+	protected TestResult packetToTestResult(DataPacket packet) {
+		String content = packet.getData();
+		int year = (int) content.charAt(4) + 2000;
+		int month = (int) content.charAt(3);
+		int date = (int) content.charAt(2);
+		int hourOfDay = (int) content.charAt(1);
+		int minute = (int) content.charAt(0);
+		int second = 0;
+
+		Calendar testDate = GregorianCalendar.getInstance();
+		testDate.set(year, month, date, hourOfDay, minute, second);
+
+		TestResult result = new TestResult();
+		result.setTestDate(testDate.getTime());
+		// 5 2 FEV1 * 100
+		result.addTestValue("FEV1", getDupleValue(content.charAt(5), content
+				.charAt(6)) / 100);
+		// 7 2 PEF * 100
+		result.addTestValue("PEF", getDupleValue(content.charAt(7), content
+				.charAt(8)) / 100);
+		// 9 2 FVC * 100
+		result.addTestValue("FVC", getDupleValue(content.charAt(9), content
+				.charAt(10)) / 100);
+		// 11 2 FER * 100
+		result.addTestValue("FER", getDupleValue(content.charAt(11), content
+				.charAt(12)) / 100);
+		// 13 2 F50 * 100
+		result.addTestValue("F50", getDupleValue(content.charAt(13), content
+				.charAt(14)) / 100);
+		// 15 2 F25 * 100
+		result.addTestValue("F25", getDupleValue(content.charAt(15), content
+				.charAt(16)) / 100);
+		// 17 2 MEF * 100
+		result.addTestValue("MEF", getDupleValue(content.charAt(17), content
+				.charAt(18)) / 100);
+		// 19 2 I50 * 100
+		result.addTestValue("I50", getDupleValue(content.charAt(19), content
+				.charAt(20)) / 100);
+		// 21 2 R50 * 100
+		result.addTestValue("R50", getDupleValue(content.charAt(21), content
+				.charAt(22)) / 100);
+		// 23 2 PIF * 100
+		result.addTestValue("PIF", getDupleValue(content.charAt(23), content
+				.charAt(24)) / 100);
+
+		// Grab patient id
+		result.setPatientId(content.substring(126, 126 + 9));
+
+		return result;
+	}
+
+	protected double getDupleValue(char x, char y) {
+		return (double) ((int) x << 8) + (int) y;
+	}
+
+	protected String byteToHex(byte b) {
+		char hexDigit[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+				'a', 'b', 'c', 'd', 'e', 'f' };
+		char[] array = { hexDigit[(b >> 4) & 0x0f], hexDigit[b & 0x0f] };
+		return new String(array);
+	}
+
+	protected String charToHex(char c) {
+		byte hi = (byte) (c >>> 8);
+		byte lo = (byte) (c & 0xff);
+		return byteToHex(hi) + byteToHex(lo);
+	}
+}
diff --git a/shim-drivers/shim-driver-label-escpos/.classpath b/shim-drivers/shim-driver-label-escpos/.classpath
new file mode 100644
index 0000000..5d96226
--- /dev/null
+++ b/shim-drivers/shim-driver-label-escpos/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/shim-drivers/shim-driver-label-escpos/.project b/shim-drivers/shim-driver-label-escpos/.project
new file mode 100644
index 0000000..b2f77e2
--- /dev/null
+++ b/shim-drivers/shim-driver-label-escpos/.project
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>shim-driver-label-escpos</name>
+	<comment>NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse.</comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+	</natures>
+</projectDescription>
diff --git a/shim-drivers/shim-driver-label-escpos/.settings/org.eclipse.jdt.core.prefs b/shim-drivers/shim-driver-label-escpos/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..52cd2f2
--- /dev/null
+++ b/shim-drivers/shim-driver-label-escpos/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+#Fri Aug 13 15:44:58 EDT 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/shim-drivers/shim-driver-label-escpos/.settings/org.eclipse.wst.common.component b/shim-drivers/shim-driver-label-escpos/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..8fab493
--- /dev/null
+++ b/shim-drivers/shim-driver-label-escpos/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="shim-driver-signature-dummy">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+    </wb-module>
+</project-modules>
diff --git a/shim-drivers/shim-driver-label-escpos/.settings/org.eclipse.wst.common.project.facet.core.xml b/shim-drivers/shim-driver-label-escpos/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..f68988c
--- /dev/null
+++ b/shim-drivers/shim-driver-label-escpos/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="jst.java" version="6.0"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/shim-drivers/shim-driver-label-escpos/.settings/org.maven.ide.eclipse.prefs b/shim-drivers/shim-driver-label-escpos/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..ec8e7f7
--- /dev/null
+++ b/shim-drivers/shim-driver-label-escpos/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Fri Jul 30 13:06:04 EDT 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/shim-drivers/shim-driver-label-escpos/pom.xml b/shim-drivers/shim-driver-label-escpos/pom.xml
new file mode 100644
index 0000000..b1e9755
--- /dev/null
+++ b/shim-drivers/shim-driver-label-escpos/pom.xml
@@ -0,0 +1,92 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<groupId>org.freemedsoftware</groupId>
+	<artifactId>shim-driver-label-escpos</artifactId>
+	<version>0.1.1</version>
+	<packaging>jar</packaging>
+
+	<name>shim-driver-label-escpos</name>
+	<url>http://freemedsoftware.org</url>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+	</properties>
+
+	<dependencies>
+
+		<dependency>
+			<groupId>org.freemedsoftware</groupId>
+			<artifactId>shim-library</artifactId>
+			<version>${version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.8.2</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>log4j</groupId>
+			<artifactId>log4j</artifactId>
+			<version>1.2.16</version>
+			<type>jar</type>
+			<scope>compile</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.rxtx</groupId>
+			<artifactId>rxtx</artifactId>
+			<version>2.2pre2</version>
+			<type>jar</type>
+			<scope>system</scope>
+      <systemPath>${basedir}/../../shim-library/deps/rxtx-2.2pre2.jar</systemPath>
+		</dependency>
+		<dependency>
+			<groupId>org.freemarker</groupId>
+			<artifactId>freemarker</artifactId>
+			<version>2.3.19</version>
+			<type>jar</type>
+			<scope>compile</scope>
+		</dependency>
+	</dependencies>
+
+	<reporting>
+		<plugins>
+			<!-- Build javadocs for this project -->
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+				<version>2.8</version>
+				<configuration>
+				</configuration>
+			</plugin>
+		</plugins>
+	</reporting>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>2.3.2</version>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+
+			<!-- Build javadocs for this project -->
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+				<version>2.8</version>
+				<configuration>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/shim-drivers/shim-driver-label-escpos/src/main/java/org/freemedsoftware/device/impl/LabelEscPosShim.java b/shim-drivers/shim-driver-label-escpos/src/main/java/org/freemedsoftware/device/impl/LabelEscPosShim.java
new file mode 100644
index 0000000..5c3d9ac
--- /dev/null
+++ b/shim-drivers/shim-driver-label-escpos/src/main/java/org/freemedsoftware/device/impl/LabelEscPosShim.java
@@ -0,0 +1,218 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device.impl;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Timer;
+
+import org.apache.log4j.Logger;
+import org.freemedsoftware.device.DeviceCapability;
+import org.freemedsoftware.device.JobStoreItem;
+import org.freemedsoftware.device.LabelPrinterInterface;
+import org.freemedsoftware.device.ParallelPrinterInterface;
+import org.freemedsoftware.device.PersistentJobStoreDAO;
+import org.freemedsoftware.device.ShimDevice;
+import org.tmatesoft.sqljet.core.SqlJetException;
+
+import freemarker.template.DefaultObjectWrapper;
+import freemarker.template.Template;
+import freemarker.template.TemplateException;
+
+ at ShimDevice(name = "Label Printer ESC-POS Shim", capability = DeviceCapability.DEVICE_LABEL_PRINTER)
+public class LabelEscPosShim implements LabelPrinterInterface {
+
+	protected Logger log = Logger.getLogger(LabelEscPosShim.class);
+
+	protected Timer timer = new Timer();
+
+	protected Integer jobId = null;
+
+	protected JobStoreItem item = null;
+
+	public final static int PROCESSING_LENGTH = 5000;
+
+	protected HashMap<String, Object> config = new HashMap<String, Object>();
+
+	protected ParallelPrinterInterface printerInterface = null;
+
+	@Override
+	public void init() throws Exception {
+		log.info("Open label printer device");
+
+		if (config == null) {
+			log.error("Config has not been set yet! Bombing out.");
+			return;
+		}
+
+		String portName = (String) config
+				.get("org.freemedsoftware.device.impl.LabelEscPosShim.port");
+		Integer timeout = Integer
+				.parseInt((String) config
+						.get("org.freemedsoftware.device.impl.LabelEscPosShim.timeout"));
+
+		log.info("Creating interface for " + portName + " with timeout "
+				+ timeout);
+
+		printerInterface = new ParallelPrinterInterface();
+		printerInterface.open(portName, timeout);
+	}
+
+	@Override
+	public boolean initJobRequest(JobStoreItem item) throws Exception {
+		jobId = item.getId();
+
+		// Update status to "PENDING" (processing)
+		item.setStatus(JobStoreItem.STATUS_PENDING);
+		try {
+			PersistentJobStoreDAO.update(item);
+		} catch (SqlJetException e) {
+			log.error(e);
+		}
+
+		this.item = item;
+
+		// Process item
+		try {
+			printLabel(item.getPrintTemplate(), item.getPrintParameters(), item
+					.getPrintCount());
+		} catch (Exception e) {
+			// For debugging...
+			e.printStackTrace();
+
+			// Attempt to update status to "ERROR"
+			item.setStatus(JobStoreItem.STATUS_ERROR);
+			try {
+				PersistentJobStoreDAO.update(item);
+			} catch (SqlJetException e2) {
+				log.error(e2);
+			}
+
+			// ... and pass this back.
+			throw e;
+		} finally {
+			// Clear everything
+			this.item = null;
+			this.jobId = null;
+		}
+
+		// Mark the task as completed if we've gotten this far
+		item.setStatus(JobStoreItem.STATUS_COMPLETED);
+		try {
+			PersistentJobStoreDAO.update(item);
+		} catch (SqlJetException e) {
+			log.error(e);
+		}
+
+		return true;
+	}
+
+	@Override
+	public void close() throws Exception {
+		log.info("Closing label printer");
+		timer.cancel();
+		if (printerInterface != null) {
+			printerInterface.close();
+		}
+	}
+
+	@Override
+	public void configure(HashMap<String, Object> config) {
+		this.config = config;
+	}
+
+	@Override
+	public List<String> getConfigurationOptions() {
+		return Arrays.asList(new String[] {
+				"org.freemedsoftware.device.impl.LabelEscPosShim.port",
+				"org.freemedsoftware.device.impl.LabelEscPosShim.timeout" });
+	}
+
+	@Override
+	public boolean isProcessing() {
+		return (jobId != null);
+	}
+
+	protected int printLabel(String printTemplate,
+			HashMap<String, String> values, Integer copies) throws IOException {
+		// Get template configuration
+		freemarker.template.Configuration cfg = this
+				.getFreemarkerConfiguration();
+
+		// Set values
+		if (values == null) {
+			values = new HashMap<String, String>();
+		}
+		values.put("esc", "\u001b");
+
+		Template template = cfg.getTemplate(printTemplate + ".template");
+
+		// Write template
+		ByteArrayOutputStream os = new ByteArrayOutputStream();
+		Writer out = new OutputStreamWriter(os);
+		for (int iter = 0; iter < copies; iter++) {
+			try {
+				log.info("Writing label copy " + (iter + 1) + " of " + copies);
+				template.process(values, out);
+				os.flush();
+				log.debug("Got " + os.size() + " bytes");
+				printerInterface.write(os.toString());
+				log.trace("LABEL: " + os.toString());
+				log.info("Write to printer device completed.");
+				out.flush();
+			} catch (TemplateException e) {
+				log.error(e);
+				return 0;
+			}
+		}
+
+		// Return successful print
+		return 1;
+	}
+
+	protected freemarker.template.Configuration getFreemarkerConfiguration()
+			throws IOException {
+		freemarker.template.Configuration cfg = new freemarker.template.Configuration();
+		cfg.setClassForTemplateLoading(getClass(), "/templates");
+		cfg.setObjectWrapper(new DefaultObjectWrapper());
+		return cfg;
+	}
+
+	@Override
+	public boolean writeToPrinter(byte[] data) throws IOException {
+		if (printerInterface != null) {
+			log.debug("Got " + data.length + " bytes");
+			printerInterface.write(new String(data));
+			log.info("Write to printer device completed.");
+		}
+		return true;
+	}
+
+}
diff --git a/shim-drivers/shim-driver-label-escpos/src/main/resources/templates/dosinglabel.template b/shim-drivers/shim-driver-label-escpos/src/main/resources/templates/dosinglabel.template
new file mode 100644
index 0000000..b7b01db
--- /dev/null
+++ b/shim-drivers/shim-driver-label-escpos/src/main/resources/templates/dosinglabel.template
@@ -0,0 +1,80 @@
+<#ftl strip_whitespace=true>
+<#-- 
+ $Id$
+ 
+ Authors:
+      Jeff Buchbinder <jeff at freemedsoftware.org>
+ 
+ FreeMED Electronic Medical Record / Practice Management System
+ Copyright (C) 1999-2012 FreeMED Software Foundation
+ 
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ 
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA. 
+-->
+<#--	Length of non-warning label portion -->
+<#assign linelength="632">
+<#--	Begin command -->
+${esc}A
+<#--	Set 4" x 1" -->
+${esc}A1<#-- -->0101<#-- -->0812
+<#--	Print header with phone number -->
+<#--	5W x 9H proportional font = XU -->
+${esc}H0030${esc}V0010${esc}XS<#-- -->${facility}
+${esc}H0400${esc}V0010${esc}XS<#-- -->Tel: ${phone}
+${esc}H0030${esc}V0025${esc}XU<#-- -->${address}
+${esc}H0000${esc}V0035${esc}FW02H0${linelength}<#-- 2 width horizontal line -->
+
+<#--	Patient name, id and dosage -->
+${esc}H0030${esc}V0040${esc}XM<#-- -->${patientname}
+${esc}H0400${esc}V0040${esc}XM<#-- -->ID #${patientid}
+${esc}H0400${esc}V0070${esc}XM<#-- -->Dose: ${dosage} mg
+
+<#--	Dosage date and lot information -->
+${esc}H0050${esc}V0070${esc}XS<#-- -->Take on : ${dosagedate}
+${esc}H0050${esc}V0088${esc}XS<#-- -->Lot     : ${lotnumber}
+<#--	Doctor and expiration -->
+${esc}H0000${esc}V0115${esc}FW01H0${linelength}<#-- 1 width horizontal line -->
+${esc}H0030${esc}V0120${esc}XS<#-- -->Doctor: ${provider}
+${esc}H0400${esc}V0120${esc}XS<#-- -->Expires: ${expires}
+<#--	Warning at the bottom -->
+${esc}H0000${esc}V0140${esc}FW02H0${linelength}<#-- 2 width horizontal line -->
+${esc}H0030${esc}V0145${esc}XS<#-- -->Controlled substance: DANGEROUS unless used as directed
+<#-- Print the warning at the end of the label ( ${l} - 790 horizontal ) -->
+${esc}H0782${esc}V0000${esc}FW01V0170<#-- 1 width vertical line -->
+${esc}H0780${esc}V0005${esc}%3${esc}XU  CAUTION: Federal Law
+${esc}H0770${esc}V0005${esc}%3${esc}XU  PROHIBITS the transfer
+${esc}H0760${esc}V0005${esc}%3${esc}XU  of this drug to any
+${esc}H0750${esc}V0005${esc}%3${esc}XU  person other than the
+${esc}H0740${esc}V0005${esc}%3${esc}XU  patient for whom it
+${esc}H0730${esc}V0005${esc}%3${esc}XU  was prescribed.
+${esc}%0<#-- reset rotation -->
+${esc}H0720${esc}V0000${esc}FW01V0170<#-- 1 width vertical line -->
+${esc}H0718${esc}V0005${esc}L0201${esc}%3${esc}XU<#-- --> TAKE ENTIRE
+${esc}H0708${esc}V0005${esc}L0201${esc}%3${esc}XU<#-- -->   CONTENTS
+${esc}L0101<#-- reset expansion of characters -->
+${esc}%0<#-- reset rotation -->
+${esc}H0698${esc}V0000${esc}FW01V0170<#-- 1 width vertical line -->
+${esc}H0696${esc}V0005${esc}L0201${esc}%3${esc}XU<#-- -->  METHADONE:
+${esc}H0686${esc}V0005${esc}L0201${esc}%3${esc}XU<#-- --> KEEP OUT OF
+${esc}H0676${esc}V0005${esc}L0201${esc}%3${esc}XU<#-- -->   REACH OF
+${esc}H0666${esc}V0005${esc}L0201${esc}%3${esc}XU<#-- -->   CHILDREN
+${esc}L0101<#-- reset expansion of characters -->
+${esc}%0<#-- reset rotation -->
+${esc}H0656${esc}V0000${esc}FW01V0170<#-- 1 width vertical line -->
+${esc}H0654${esc}V0005${esc}L0201${esc}%3${esc}XU<#-- -->ORAL USE ONLY
+${esc}L0101<#-- reset expansion of characters -->
+${esc}%0<#-- reset rotation -->
+${esc}H0644${esc}V0000${esc}FW01V0170<#-- 1 width vertical line -->
+<#--	End command -->
+${esc}Z\x0003
diff --git a/shim-drivers/shim-driver-label-escpos/src/main/resources/templates/toxlabel.template b/shim-drivers/shim-driver-label-escpos/src/main/resources/templates/toxlabel.template
new file mode 100644
index 0000000..1377482
--- /dev/null
+++ b/shim-drivers/shim-driver-label-escpos/src/main/resources/templates/toxlabel.template
@@ -0,0 +1,53 @@
+<#ftl strip_whitespace=true>
+<#-- 
+ $Id$
+ 
+ Authors:
+      Jeff Buchbinder <jeff at freemedsoftware.org>
+ 
+ FreeMED Electronic Medical Record / Practice Management System
+ Copyright (C) 1999-2012 FreeMED Software Foundation
+ 
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ 
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA. 
+-->
+<#--	Length of non-warning label portion -->
+<#assign linelength="632">
+<#--       Begin command -->
+${esc}A
+<#--       Set 4" x 1" -->
+${esc}A101010812
+<#--       Print header with phone number -->
+<#--       5W x 9H proportional font = XU -->
+${esc}H0030${esc}V0010${esc}XS<#-- -->${facility}
+${esc}H0400${esc}V0010${esc}XS<#-- -->Tel: ${phone}
+${esc}H0030${esc}V0025${esc}XU<#-- -->${address}
+${esc}H0000${esc}V0035${esc}FW02H0${linelength}<#-- 2 width horizontal line -->
+<#--       Patient name, id and dosage -->
+${esc}H0030${esc}V0040${esc}XM<#-- -->${patientid}
+${esc}H0400${esc}V0040${esc}XM<#-- -->DOB:${patientdob}
+${esc}H0030${esc}V0100${esc}XS<#-- -->Test:${testname}
+${esc}H0030${esc}V0115${esc}XS${substances}
+<#--       Dosage date and lot information -->
+${esc}H0050${esc}V0070${esc}XS<#-- -->Date : ${testdate}
+<#--       Doctor and expiration -->
+${esc}H0000${esc}V0129${esc}FW01H0<#-- -->${linelength}<#-- 1 width horizontal line -->
+${esc}H0030${esc}V0140${esc}XS<#-- -->Doctor: ${provider}
+${esc}H0400${esc}V0140${esc}XS<#-- -->Counselor : ${counselor}
+<#--       Warning at the bottom -->
+${esc}H0000${esc}V0160${esc}FW02H0${linelength}<#-- 2 width horizontal line -->
+${esc}L0101<#-- reset expansion of characters -->
+${esc}%0<#-- reset rotation-->
+<#--       End command -->
+${esc}Z\x0003
diff --git a/shim-drivers/shim-driver-signature-dummy/.classpath b/shim-drivers/shim-driver-signature-dummy/.classpath
new file mode 100644
index 0000000..5d96226
--- /dev/null
+++ b/shim-drivers/shim-driver-signature-dummy/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/shim-drivers/shim-driver-signature-dummy/.project b/shim-drivers/shim-driver-signature-dummy/.project
new file mode 100644
index 0000000..6d96735
--- /dev/null
+++ b/shim-drivers/shim-driver-signature-dummy/.project
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>shim-driver-signature-dummy</name>
+	<comment>NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse.</comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+	</natures>
+</projectDescription>
diff --git a/shim-drivers/shim-driver-signature-dummy/.settings/org.eclipse.jdt.core.prefs b/shim-drivers/shim-driver-signature-dummy/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..52cd2f2
--- /dev/null
+++ b/shim-drivers/shim-driver-signature-dummy/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+#Fri Aug 13 15:44:58 EDT 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/shim-drivers/shim-driver-signature-dummy/.settings/org.eclipse.wst.common.component b/shim-drivers/shim-driver-signature-dummy/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..8fab493
--- /dev/null
+++ b/shim-drivers/shim-driver-signature-dummy/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="shim-driver-signature-dummy">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+    </wb-module>
+</project-modules>
diff --git a/shim-drivers/shim-driver-signature-dummy/.settings/org.eclipse.wst.common.project.facet.core.xml b/shim-drivers/shim-driver-signature-dummy/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..f68988c
--- /dev/null
+++ b/shim-drivers/shim-driver-signature-dummy/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="jst.java" version="6.0"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/shim-drivers/shim-driver-signature-dummy/.settings/org.maven.ide.eclipse.prefs b/shim-drivers/shim-driver-signature-dummy/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..ec8e7f7
--- /dev/null
+++ b/shim-drivers/shim-driver-signature-dummy/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Fri Jul 30 13:06:04 EDT 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/shim-drivers/shim-driver-signature-dummy/pom.xml b/shim-drivers/shim-driver-signature-dummy/pom.xml
new file mode 100644
index 0000000..c8a8f92
--- /dev/null
+++ b/shim-drivers/shim-driver-signature-dummy/pom.xml
@@ -0,0 +1,77 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<groupId>org.freemedsoftware</groupId>
+	<artifactId>shim-driver-signature-dummy</artifactId>
+	<version>0.1.1</version>
+	<packaging>jar</packaging>
+
+	<name>shim-driver-signature-dummy</name>
+	<url>http://freemedsoftware.org</url>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+	</properties>
+
+	<dependencies>
+
+		<dependency>
+			<groupId>org.freemedsoftware</groupId>
+			<artifactId>shim-library</artifactId>
+			<version>${version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.8.2</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>log4j</groupId>
+			<artifactId>log4j</artifactId>
+			<version>1.2.16</version>
+			<type>jar</type>
+			<scope>compile</scope>
+		</dependency>
+	</dependencies>
+
+	<reporting>
+		<plugins>
+			<!-- Build javadocs for this project -->
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+				<version>2.8</version>
+				<configuration>
+				</configuration>
+			</plugin>
+		</plugins>
+	</reporting>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>2.3.2</version>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+
+			<!-- Build javadocs for this project -->
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+				<version>2.8</version>
+				<configuration>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/shim-drivers/shim-driver-signature-dummy/src/main/java/org/freemedsoftware/device/impl/SignatureDummyShim.java b/shim-drivers/shim-driver-signature-dummy/src/main/java/org/freemedsoftware/device/impl/SignatureDummyShim.java
new file mode 100644
index 0000000..422e543
--- /dev/null
+++ b/shim-drivers/shim-driver-signature-dummy/src/main/java/org/freemedsoftware/device/impl/SignatureDummyShim.java
@@ -0,0 +1,114 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device.impl;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.apache.log4j.Logger;
+import org.freemedsoftware.device.DeviceCapability;
+import org.freemedsoftware.device.JobStoreItem;
+import org.freemedsoftware.device.PersistentJobStoreDAO;
+import org.freemedsoftware.device.ShimDevice;
+import org.freemedsoftware.device.SignatureInterface;
+import org.tmatesoft.sqljet.core.SqlJetException;
+
+ at ShimDevice(name = "Signature Dummy Shim", capability = DeviceCapability.DEVICE_SIGNATURE_TABLET)
+public class SignatureDummyShim implements SignatureInterface {
+
+	protected Logger log = Logger.getLogger(DummyShim.class);
+
+	protected Timer timer = new Timer();
+
+	protected Integer jobId = null;
+
+	protected JobStoreItem item = null;
+
+	public final static int PROCESSING_LENGTH = 5000;
+
+	protected class ProcessingTimerTask extends TimerTask {
+
+		@Override
+		public void run() {
+			item.setStatus(JobStoreItem.STATUS_COMPLETED);
+			try {
+				PersistentJobStoreDAO.update(item);
+			} catch (SqlJetException e) {
+				log.error(e);
+			}
+
+			// Clear job and item objects
+			jobId = null;
+			item = null;
+		}
+
+	}
+
+	@Override
+	public void init() {
+		log.info("open/init dummy sig device");
+	}
+
+	@Override
+	public boolean initJobRequest(JobStoreItem item) throws Exception {
+		jobId = item.getId();
+
+		// Update status to "PENDING" (processing)
+		item.setStatus(JobStoreItem.STATUS_PENDING);
+		try {
+			PersistentJobStoreDAO.update(item);
+		} catch (SqlJetException e) {
+			log.error(e);
+		}
+
+		this.item = item;
+		timer.schedule(new ProcessingTimerTask(), PROCESSING_LENGTH);
+		return true;
+	}
+
+	@Override
+	public void close() throws Exception {
+		log.info("close dummy sig device");
+		timer.cancel();
+	}
+
+	@Override
+	public void configure(HashMap<String, Object> config) {
+		log.info("configure dummy sig device");
+	}
+
+	@Override
+	public List<String> getConfigurationOptions() {
+		return null;
+	}
+
+	@Override
+	public boolean isProcessing() {
+		return (jobId != null);
+	}
+
+}
diff --git a/shim-drivers/shim-driver-signature-topaz/.classpath b/shim-drivers/shim-driver-signature-topaz/.classpath
new file mode 100644
index 0000000..8a3cf79
--- /dev/null
+++ b/shim-drivers/shim-driver-signature-topaz/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/shim-drivers/shim-driver-signature-topaz/.project b/shim-drivers/shim-driver-signature-topaz/.project
new file mode 100644
index 0000000..46ab067
--- /dev/null
+++ b/shim-drivers/shim-driver-signature-topaz/.project
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>shim-driver-signature-topaz</name>
+	<comment>NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse.</comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+	</natures>
+</projectDescription>
diff --git a/shim-drivers/shim-driver-signature-topaz/.settings/org.eclipse.jdt.core.prefs b/shim-drivers/shim-driver-signature-topaz/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..a5108ba
--- /dev/null
+++ b/shim-drivers/shim-driver-signature-topaz/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+#Fri Aug 13 15:38:48 EDT 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/shim-drivers/shim-driver-signature-topaz/.settings/org.eclipse.wst.common.component b/shim-drivers/shim-driver-signature-topaz/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..40ad75a
--- /dev/null
+++ b/shim-drivers/shim-driver-signature-topaz/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="shim-driver-topaz">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+    </wb-module>
+</project-modules>
diff --git a/shim-drivers/shim-driver-signature-topaz/.settings/org.eclipse.wst.common.project.facet.core.xml b/shim-drivers/shim-driver-signature-topaz/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..f68988c
--- /dev/null
+++ b/shim-drivers/shim-driver-signature-topaz/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="jst.java" version="6.0"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/shim-drivers/shim-driver-signature-topaz/.settings/org.maven.ide.eclipse.prefs b/shim-drivers/shim-driver-signature-topaz/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..ec8e7f7
--- /dev/null
+++ b/shim-drivers/shim-driver-signature-topaz/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Fri Jul 30 13:06:04 EDT 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/shim-drivers/shim-driver-signature-topaz/README b/shim-drivers/shim-driver-signature-topaz/README
new file mode 100644
index 0000000..dc46b8b
--- /dev/null
+++ b/shim-drivers/shim-driver-signature-topaz/README
@@ -0,0 +1,22 @@
+$Id$
+
+SHIM driver for Topaz System SigPlus-driver based signature pads.
+
+This driver has been tested with:
+
+	SignatureGem4x5
+	SignatureGemLCD1x5
+
+To install properly in udev-based systems, create
+"/etc/udev/rules.d/99-topaz.rules" with the following content:
+
+  SUBSYSTEM=="usb", SYSFS{idVendor}=="06a8", MODE="0666"
+
+This should allow all users to read and write data to/from any
+Topaz Systems tablet.
+
+JNI libraries for your native JVM should be installed in
+java.library.path, and are located in the distribution under
+"native", which is normally $JAVA_HOME/jre/lib/$ARCH/ (where
+$ARCH is amd64, i386, etc).
+
diff --git a/shim-drivers/shim-driver-signature-topaz/deps/commapi-2.0.3.jar b/shim-drivers/shim-driver-signature-topaz/deps/commapi-2.0.3.jar
new file mode 100644
index 0000000..1ed64c2
Binary files /dev/null and b/shim-drivers/shim-driver-signature-topaz/deps/commapi-2.0.3.jar differ
diff --git a/shim-drivers/shim-driver-signature-topaz/deps/sigplus-2.60.jar b/shim-drivers/shim-driver-signature-topaz/deps/sigplus-2.60.jar
new file mode 100644
index 0000000..88949cc
Binary files /dev/null and b/shim-drivers/shim-driver-signature-topaz/deps/sigplus-2.60.jar differ
diff --git a/shim-drivers/shim-driver-signature-topaz/native/i686-unknown-linux-gnu/libSigUsb.so b/shim-drivers/shim-driver-signature-topaz/native/i686-unknown-linux-gnu/libSigUsb.so
new file mode 100644
index 0000000..c02e1e5
Binary files /dev/null and b/shim-drivers/shim-driver-signature-topaz/native/i686-unknown-linux-gnu/libSigUsb.so differ
diff --git a/shim-drivers/shim-driver-signature-topaz/native/win32/SigUsb.dll b/shim-drivers/shim-driver-signature-topaz/native/win32/SigUsb.dll
new file mode 100644
index 0000000..cdd692c
Binary files /dev/null and b/shim-drivers/shim-driver-signature-topaz/native/win32/SigUsb.dll differ
diff --git a/shim-drivers/shim-driver-signature-topaz/native/win32/TopazAuto.inf b/shim-drivers/shim-driver-signature-topaz/native/win32/TopazAuto.inf
new file mode 100644
index 0000000..b38f4aa
--- /dev/null
+++ b/shim-drivers/shim-driver-signature-topaz/native/win32/TopazAuto.inf
@@ -0,0 +1,60 @@
+; Installation inf for the Topaz USB Tablet
+;
+; (c) Copyright 2000-2002, Topaz Systems, Inc.
+;
+
+[Version]
+Signature="$CHICAGO$"
+Class=USB
+ClassGUID={36FC9E60-C465-11CF-8056-444553540000}
+provider=%Topaz%
+DriverVer=5/15/2002
+
+
+[Manufacturer]
+%MfgName%=Topaz
+
+[Topaz]
+%USB\VID_06A8&PID_0042.DeviceDesc%=TOPAZUSB.Dev, USB\VID_06A8&PID_0042
+
+[PreCopySection]
+HKR,,NoSetupUI,,1
+
+[DestinationDirs]
+DefaultDestDir=12
+
+[TOPAZUSB.Dev]
+AddReg=TOPAZUSB.AddReg
+
+[TOPAZUSB.Dev.NT]
+AddReg=TOPAZUSB.AddReg
+
+[TOPAZUSB.Dev.NT.Services]
+Addservice = TOPAZUSB, 0x00000002, TOPAZUSB.AddService
+
+[TOPAZUSB.AddService]
+DisplayName    = %TOPAZUSB.SvcDesc%
+ServiceType    = 1                  ; SERVICE_KERNEL_DRIVER
+StartType      = 3                  ; SERVICE_DEMAND_START
+ErrorControl   = 1                  ; SERVICE_ERROR_NORMAL
+ServiceBinary  = %12%\TOPAZUSB.sys
+LoadOrderGroup = Base
+
+[TOPAZUSB.AddReg]
+HKR,,DevLoader,,*ntkern
+HKR,,NTMPDriver,,TOPAZUSB.sys
+;HKLM,"System\Currentcontrolset\Services\TopazUsb\Parameters","MaximumTransferSize",0x10001,4096
+;HKLM,"System\Currentcontrolset\Services\TopazUsb\Parameters","DebugLevel",0x10001,2
+
+
+
+;---------------------------------------------------------------;
+
+[Strings]
+Topaz="Topaz"
+MfgName="Topaz"
+USB\VID_06A8&PID_0042.DeviceDesc="TopazUsb.Sys Topaz USB Tablet"
+TOPAZUSB.SvcDesc="TopazUsb.Sys Topaz Tablet USB Driver"
+
+
+
diff --git a/shim-drivers/shim-driver-signature-topaz/native/win32/TopazUsb.sys b/shim-drivers/shim-driver-signature-topaz/native/win32/TopazUsb.sys
new file mode 100644
index 0000000..1df8073
Binary files /dev/null and b/shim-drivers/shim-driver-signature-topaz/native/win32/TopazUsb.sys differ
diff --git a/shim-drivers/shim-driver-signature-topaz/pom.xml b/shim-drivers/shim-driver-signature-topaz/pom.xml
new file mode 100644
index 0000000..f68b281
--- /dev/null
+++ b/shim-drivers/shim-driver-signature-topaz/pom.xml
@@ -0,0 +1,89 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<groupId>org.freemedsoftware</groupId>
+	<artifactId>shim-driver-signature-topaz</artifactId>
+	<version>0.1.1</version>
+	<packaging>jar</packaging>
+
+	<name>shim-driver-signature-topaz</name>
+	<url>http://freemedsoftware.org</url>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+	</properties>
+
+	<dependencies>
+
+		<dependency>
+			<groupId>org.freemedsoftware</groupId>
+			<artifactId>shim-library</artifactId>
+			<version>${version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.8.2</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.rxtx</groupId>
+			<artifactId>rxtx</artifactId>
+			<version>2.2pre2</version>
+			<type>jar</type>
+			<scope>system</scope>
+      <systemPath>${basedir}/../../shim-library/deps/rxtx-2.2pre2.jar</systemPath>
+		</dependency>
+
+		<dependency>
+			<groupId>commapi</groupId>
+			<artifactId>commapi</artifactId>
+			<version>2.0.3</version>
+			<type>jar</type>
+			<scope>system</scope>
+			<systemPath>${basedir}/deps/commapi-2.0.3.jar</systemPath>
+		</dependency>
+
+		<dependency>
+			<groupId>sigplus</groupId>
+			<artifactId>sigplus</artifactId>
+			<version>2.60</version>
+			<type>jar</type>
+			<scope>system</scope>
+			<systemPath>${basedir}/deps/sigplus-2.60.jar</systemPath>
+		</dependency>
+
+		<dependency>
+			<groupId>org.tmatesoft.sqljet</groupId>
+			<artifactId>sqljet</artifactId>
+			<version>1.0.4</version>
+			<scope>compile</scope>
+		</dependency>
+
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>2.3.2</version>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+	<repositories>
+		<repository>
+			<id>tmate</id>
+			<url>http://maven.svnkit.com/maven2</url>
+		</repository>
+	</repositories>
+
+</project>
diff --git a/shim-drivers/shim-driver-signature-topaz/src/main/java/org/freemedsoftware/device/impl/SignatureTopazShim.java b/shim-drivers/shim-driver-signature-topaz/src/main/java/org/freemedsoftware/device/impl/SignatureTopazShim.java
new file mode 100644
index 0000000..4e26885
--- /dev/null
+++ b/shim-drivers/shim-driver-signature-topaz/src/main/java/org/freemedsoftware/device/impl/SignatureTopazShim.java
@@ -0,0 +1,598 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device.impl;
+
+import java.awt.Font;
+import java.awt.image.BufferedImage;
+import java.beans.Beans;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.atomic.AtomicLong;
+
+import javax.imageio.ImageIO;
+
+import org.apache.log4j.BasicConfigurator;
+import org.apache.log4j.Logger;
+import org.freemedsoftware.device.DeviceCapability;
+import org.freemedsoftware.device.JobStoreItem;
+import org.freemedsoftware.device.PersistentJobStoreDAO;
+import org.freemedsoftware.device.ShimDevice;
+import org.freemedsoftware.device.SignatureInterface;
+
+import com.topaz.sigplus.SigPlus;
+import com.topaz.sigplus.SigPlusEvent0;
+import com.topaz.sigplus.SigPlusListener;
+import com.topaz.sigplus.TopazSigCapData;
+
+ at ShimDevice(name = "Topaz Signature Shim", capability = DeviceCapability.DEVICE_SIGNATURE_TABLET)
+public class SignatureTopazShim implements SignatureInterface, SigPlusListener {
+
+	protected Logger log = Logger.getLogger(SignatureTopazShim.class);
+
+	protected SigPlus sigObj = null;
+
+	protected Integer currentJobId = null;
+
+	protected JobStoreItem job = null;
+
+	/**
+	 * Amount of time in milliseconds to wait between signature polling.
+	 */
+	protected final static int SIGNATURE_WAIT_DURATION = 500;
+
+	/**
+	 * Maximum amount of time to wait after last signature point recorded.
+	 */
+	protected final static int SIGNATURE_MAXIMUM_WAIT = 2000;
+
+	/**
+	 * Wait this much time in milliseconds before giving up.
+	 */
+	protected final static int SIGNATURE_INITIAL_WAIT = 15000;
+
+	protected final static int SIGNATURE_MINIMUM_POINTS = 10;
+
+	/**
+	 * Number of milliseconds to display signature confirmation message.
+	 */
+	protected final static int DISPLAY_SIGNATURE_CONFIRMATION = 7000;
+
+	protected Map<String, Object> config = new HashMap<String, Object>();
+
+	protected static Timer timer = new Timer();
+
+	protected static AtomicLong lastSeen = new AtomicLong();
+
+	protected static long requestTime = 0L;
+
+	protected static int numSigPoints = 0;
+
+	protected static String LCD_FONT_TYPEFACE = Font.SERIF;
+
+	protected static String SIGNATURE_CONFIRMATION_MESSAGE = "Your signature has been recorded.";
+
+	protected static String SIGNATURE_NONE_MESSAGE = "No signature has been given!";
+
+	protected static Font tabletFont = Font.getFont(LCD_FONT_TYPEFACE);
+
+	protected class LcdWriteDestination {
+		/**
+		 * 0 = Foreground
+		 */
+		public final static int FOREGROUND = 0;
+		/**
+		 * 1 = Background memory in tablet
+		 */
+		public final static int BACKGROUND_MEMORY = 1;
+	}
+
+	protected class LcdCaptureMode {
+		/**
+		 * Mode 0 no LCD commands are sent to the tablet
+		 */
+		public final static int NO_LCD = 0;
+		/**
+		 * Mode 1 - sets capture mode to be active with Autoerase in the tablet
+		 */
+		public final static int ENABLED_AUTOERASE = 1;
+		/**
+		 * Mode 2 - sets the tablet to persistent ink capture without autoerase
+		 */
+		public final static int ENABLED = 2;
+		/**
+		 * Mode 3 - signature ink is displayed inverted on a suitable dark
+		 * background set using the Graphic functions.
+		 */
+		public final static int ENABLED_INVERTED = 3;
+	}
+
+	protected class LcdWriteMode {
+		/**
+		 * Mode 0 - Clear: The Display is cleared at the specified location.
+		 */
+		public final static int CLEAR = 0;
+		/**
+		 * Mode 1 - Complement: The Display is complemented at the specified
+		 * location.
+		 */
+		public final static int COMPLEMENT = 1;
+		/**
+		 * Mode 2 - WriteOpaque: The contents of the background memory in the
+		 * tablet are transferred to the LCD display, overwriting the contents
+		 * of the LCD display.
+		 */
+		public final static int WRITE_OPAQUE = 2;
+		/**
+		 * Mode 3 - WriteTransparent: The contents of the background memory in
+		 * the tablet are combined with and transferred to the visible LCD
+		 * memory
+		 */
+		public final static int WRITE_TRANSPARENT = 3;
+	}
+
+	protected class TopazTimerSignatureClearDisplayTask extends TimerTask {
+		@Override
+		public void run() {
+			// Only do this if there's no current job id running
+			if (currentJobId == null) {
+				log.info("Clearing display.");
+				clearTabletLCD();
+				// sigObj.lcdRefresh(0, 0, 0, sigObj.getTabletLCDXSize(),
+				// sigObj.getTabletLCDYSize());
+				// sigObj.setLCDCaptureMode(LcdCaptureMode.NO_LCD);
+				// sigObj.setEnabled(false);
+				// sigObj.setTabletState(0);
+				// sigObj.clearTablet();
+			} else {
+				log.warn("Attempted to clear LCD but job id of " + currentJobId
+						+ " is present");
+			}
+		}
+	}
+
+	protected class TopazTimerTask extends TimerTask {
+
+		@Override
+		public void run() {
+			log.info("TopazTimerTask running");
+
+			int sigPoints = 0;
+			try {
+				sigPoints = sigObj.getSignatureData().m_PointArray.length;
+			} catch (Exception ex) {
+				log.warn("Could not fetch signature data point length"
+						+ ", dropping back into loop", ex);
+				return;
+			}
+
+			// If we have no points at all ...
+			if (sigPoints == 0) {
+				// ... and we have been waiting for less than
+				// SIGNATURE_INITIAL_WAIT ms
+				if ((System.currentTimeMillis() - requestTime) < SIGNATURE_INITIAL_WAIT) {
+					log.debug("No points seen yet, waiting for about "
+							+ (SIGNATURE_INITIAL_WAIT - (System
+									.currentTimeMillis() - requestTime))
+							+ " ms before giving up");
+
+					// Go back to waiting.
+					return;
+				} else {
+					log.warn("Failed to see any points after "
+							+ (System.currentTimeMillis() - requestTime)
+							+ " ms, aborting.");
+
+					// Cancel the job.
+					cancelJob();
+
+					// Clear everything
+					log.info("Clearing signature job id");
+					currentJobId = null;
+					job = null;
+					numSigPoints = 0;
+					lastSeen.set(0L);
+
+					log.info("Clearing tablet.");
+					clearTabletLCD();
+					// sigObj.setEnabled(false);
+					// sigObj.setTabletState(0);
+					// sigObj.clearTablet();
+
+					log.info("Cancelling timer.");
+					cancel();
+
+					writeTabletMessage(0, 0, SIGNATURE_NONE_MESSAGE);
+
+					// Clear the LCD after certain number of ms.
+					timer.schedule(new TopazTimerSignatureClearDisplayTask(),
+							DISPLAY_SIGNATURE_CONFIRMATION);
+				}
+			}
+
+			log.debug("numSigPoints = " + numSigPoints
+					+ " / sigObj.getSignatureData().m_PointArray.length = "
+					+ sigPoints);
+			if (sigPoints > numSigPoints) {
+				// Bump up when an event was last seen to now.
+				lastSeen.set(System.currentTimeMillis());
+
+				// ... and increase the counter
+				numSigPoints = sigPoints;
+
+				// Wait until next task execution
+				log
+						.debug("New points seen since last polling, dropping back into loop.");
+				return;
+			}
+
+			if ((System.currentTimeMillis() - lastSeen.get()) < SIGNATURE_MAXIMUM_WAIT) {
+				log
+						.debug("Dropping back into loop, need to wait a little longer.");
+				return;
+			}
+
+			// Test to see if anything is there
+			if (sigPoints < SIGNATURE_MINIMUM_POINTS) {
+				// Wait until next task execution
+				log.debug("Not enough points recorded, back to waiting");
+				return;
+			}
+
+			// If everything else works properly, we're going to deal with the
+			// data we've got.
+
+			// "Handle" the signature
+			log.info("Attempting to handle signature");
+			handleSignature();
+
+			// Clear everything
+			log.info("Clearing signature job id");
+			job = null;
+			currentJobId = null;
+			numSigPoints = 0;
+			lastSeen.set(0L);
+			log.info("Clearing pad.");
+			clearTabletLCD();
+			// sigObj.setEnabled(false);
+			// sigObj.setTabletState(0);
+			// sigObj.clearTablet();
+
+			// Just cancel timer task, otherwise the <Timer> object isn't
+			// reusable.
+			log.info("Cancelling timer task.");
+			cancel();
+
+			writeTabletMessage(0, 0, SIGNATURE_CONFIRMATION_MESSAGE);
+
+			// Clear the LCD after certain number of ms.
+			timer.schedule(new TopazTimerSignatureClearDisplayTask(),
+					DISPLAY_SIGNATURE_CONFIRMATION);
+		}
+	}
+
+	@Override
+	public void configure(HashMap<String, Object> config) {
+		log.info("Loading configuration");
+		this.config = config;
+	}
+
+	@Override
+	public List<String> getConfigurationOptions() {
+		return Arrays
+				.asList(new String[] {
+						"org.freemedsoftware.device.impl.SignatureTopazShim.tabletModel",
+						"org.freemedsoftware.device.impl.SignatureTopazShim.tabletPort" });
+	}
+
+	@Override
+	public boolean isProcessing() {
+		return (currentJobId != null);
+	}
+
+	@Override
+	public void init() throws Exception {
+		// Load Topaz SigPlus driver on top of rxtx or HID driver
+		log.debug("init()");
+		ClassLoader cl = (SigPlus.class).getClassLoader();
+		log.debug("Instantiating Topaz SigPlus driver");
+		sigObj = (SigPlus) Beans.instantiate(cl, "com.topaz.sigplus.SigPlus");
+
+		// Clear all tablet configuration
+		sigObj.clearTablet();
+
+		// Pull from actual configuration
+		try {
+			sigObj
+					.setTabletModel((String) config
+							.get("org.freemedsoftware.device.impl.SignatureTopazShim.tabletModel"));
+			sigObj
+					.setTabletComPort((String) config
+							.get("org.freemedsoftware.device.impl.SignatureTopazShim.tabletPort"));
+		} catch (Exception ex) {
+			log.error(ex);
+			throw ex;
+		}
+
+		// Attach event listener
+		sigObj.addSigPlusListener(this);
+
+		// By default, disable this object until it has to become active
+		sigObj.setEnabled(false);
+	}
+
+	@Override
+	public void close() throws Exception {
+		if (timer != null) {
+			log.info("Cancelling timer");
+			timer.cancel();
+		}
+		if (sigObj != null) {
+			log.info("Closing/clearing signature pad");
+			clearTabletLCD();
+			// sigObj.setEnabled(false);
+			// sigObj.setTabletState(0);
+			// sigObj.clearTablet();
+			sigObj = null;
+		}
+	}
+
+	@Override
+	public boolean initJobRequest(JobStoreItem item) throws Exception {
+		// If we're already processing a request, do not progress any further.
+		if (currentJobId != null) {
+			log.error("Job in progress already for pad.");
+			return false;
+		} else {
+			if (item == null) {
+				job = new JobStoreItem();
+				job.setId(0);
+				job.setDisplayText("Patient: Rufus T Firefly");
+				job.setStatus("PENDING");
+			} else {
+				log.info("Setting current jobId to " + item.getId());
+				job = item;
+			}
+		}
+
+		// Record the request time
+		requestTime = System.currentTimeMillis();
+
+		// Clear tablet
+		sigObj.clearTablet();
+
+		// Store uid locally
+		currentJobId = job.getId();
+
+		// Reset counters
+		numSigPoints = 0;
+		lastSeen.set(0L);
+
+		sigObj.setEnabled(true);
+		sigObj.autoKeyStart();
+		sigObj.setAutoKeyData("Sample Encryption Data");
+		sigObj.autoKeyFinish();
+		sigObj.setEncryptionMode(2);
+		sigObj.setSavePressureData(true);
+		sigObj.setSigCompressionMode(1);
+
+		// Enable "capture" mode
+		sigObj.setTabletState(1);
+
+		// Attempt to readjust LCD on models which support it
+		try {
+			log.info("X size = " + sigObj.getTabletLCDXSize() + ", Y size = "
+					+ sigObj.getTabletLCDYSize());
+			sigObj.lcdRefresh(0, 0, 0, sigObj.getTabletLCDXSize(), sigObj
+					.getTabletLCDYSize());
+			sigObj.setLCDCaptureMode(LcdCaptureMode.ENABLED);
+			sigObj.lcdWriteString(LcdWriteDestination.FOREGROUND,
+					LcdWriteMode.WRITE_OPAQUE, 0, 0, "Please sign below",
+					tabletFont);
+			sigObj.lcdWriteString(LcdWriteDestination.FOREGROUND,
+					LcdWriteMode.WRITE_OPAQUE, 0,
+					sigObj.getTabletLCDYSize() - 20, job.getDisplayText(),
+					tabletFont);
+		} catch (Exception ex) {
+			log.info("LCD adjustment failed with " + ex.toString());
+		}
+
+		// Schedule a timer task to attempt to poll the pad
+		lastSeen.set(System.currentTimeMillis());
+		timer.schedule(new TopazTimerTask(), SIGNATURE_WAIT_DURATION,
+				SIGNATURE_WAIT_DURATION);
+
+		return true;
+	}
+
+	protected void clearTabletLCD() {
+		if (sigObj != null) {
+			sigObj.lcdRefresh(0, 0, 0, sigObj.getTabletLCDXSize(), sigObj
+					.getTabletLCDYSize());
+			sigObj.setLCDCaptureMode(LcdCaptureMode.NO_LCD);
+			sigObj.setEnabled(false);
+			sigObj.setTabletState(0);
+			sigObj.clearTablet();
+		}
+	}
+
+	protected void writeTabletMessage(int x, int y, String message) {
+		// Attempt to display confirmation message
+		try {
+			log.info("Attempting to display message.");
+			sigObj.setTabletState(1);
+
+			sigObj.setLCDCaptureMode(LcdCaptureMode.ENABLED);
+			sigObj.lcdWriteString(LcdWriteDestination.FOREGROUND,
+					LcdWriteMode.WRITE_OPAQUE, x, y, message, tabletFont);
+		} catch (Throwable t) {
+			log.warn("Failed to properly write message", t);
+			sigObj.setTabletState(0);
+		}
+	}
+
+	public void handleKeyPadData(SigPlusEvent0 event) {
+	}
+
+	public void handleNewTabletData(SigPlusEvent0 event) {
+		// Update the record of when an event was last seen.
+		lastSeen.set(System.currentTimeMillis());
+
+		if (currentJobId == null) {
+			log.error("No current job id, unexpected data");
+		}
+	}
+
+	protected void handleSignature() {
+		// mySigString = sigObj.getSigString();
+		sigObj.setSigCompressionMode(0);
+		sigObj.setEncryptionMode(0);
+		sigObj.setKeyString("0000000000000000");
+
+		// Attempt to readjust LCD on models which support it
+		try {
+			sigObj.lcdRefresh(0, 0, 0, 640, 480);
+			sigObj.setLCDCaptureMode(LcdCaptureMode.ENABLED_AUTOERASE);
+		} catch (Exception ex) {
+			log.info("LCD adjustment failed with " + ex.toString());
+		}
+
+		TopazSigCapData sigData = sigObj.getSignatureData();
+		log.debug(sigData.m_byRawData);
+		job.setSignatureRaw(sigData.m_byRawData.getBytes());
+
+		// Store data in object
+		log.info("Storing data.");
+
+		// Create PNG image
+		try {
+			BufferedImage sigImage = sigObj.sigImage();
+			int w = sigImage.getWidth(null);
+			int h = sigImage.getHeight(null);
+			log.info("getWidth/getHeight returned : w = " + w + ", h = " + h);
+			try {
+				w = sigObj.getTabletLCDXSize();
+				h = sigObj.getTabletLCDYSize();
+				log.info("Used LCD to get dimensions of w = " + w + ", h = "
+						+ h);
+			} catch (Exception ex) {
+				log.warn(ex);
+			}
+
+			sigObj.setImageJustifyMode(5);
+			sigObj.setImagePenWidth(1);
+			sigObj.setImageXSize(w);
+			sigObj.setImageYSize(h);
+
+			// Redundant.
+			sigImage = sigObj.sigImage();
+
+			int[] pixels = new int[((w * h) * 2) + 1];
+			log.debug("pixel array length = " + pixels.length);
+			sigImage.setRGB(0, 0, 0, 0, pixels, 0, 0);
+			ByteArrayOutputStream fos = new ByteArrayOutputStream();
+
+			try {
+				ImageIO.write(sigImage, "png", fos);
+			} catch (IOException ex) {
+				log.error(ex);
+			}
+			try {
+				fos.close();
+			} catch (IOException ex) {
+				log.error(ex);
+			}
+			log.debug("Populating signature image in job item.");
+			job.setSignatureImage(fos.toByteArray());
+		} catch (Throwable t) {
+			log.error(t);
+		}
+
+		// Disable tablet capture mode
+		sigObj.setTabletState(0);
+
+		log.info("Recording job status");
+		job.setStatus(JobStoreItem.STATUS_COMPLETED);
+		if (job.getId() != 0) {
+			log.info("Writing to persistent job store");
+			try {
+				PersistentJobStoreDAO.update(job);
+			} catch (Exception e) {
+				log.error("Failed to write", e);
+			}
+		} else {
+			log
+					.info("Skipping persistent job store write, as this is a test case.");
+			log.debug("length = " + job.getSignatureImage().length
+					+ ", data = " + new String(job.getSignatureImage()));
+		}
+	}
+
+	public void handleTabletTimerEvent(SigPlusEvent0 event) {
+	}
+
+	public void cancelJob() {
+		log.info("Recording error job status");
+		job.setStatus(JobStoreItem.STATUS_ERROR);
+		if (job.getId() != 0) {
+			log.info("Writing to persistent job store");
+			try {
+				PersistentJobStoreDAO.update(job);
+			} catch (Exception e) {
+				log.error("Failed to write", e);
+			}
+		} else {
+			log
+					.info("Skipping persistent job store write, as this is a test case.");
+		}
+	}
+
+	/**
+	 * Main method for testing only
+	 * 
+	 * @param args
+	 * @throws Exception
+	 */
+	public static void main(String[] args) throws Exception {
+		BasicConfigurator.configure();
+		SignatureTopazShim s = new SignatureTopazShim();
+		HashMap<String, Object> c = new HashMap<String, Object>();
+		c.put("org.freemedsoftware.device.impl.SignatureTopazShim.tabletModel",
+				"SignatureGemLCD1X5");
+		c.put("org.freemedsoftware.device.impl.SignatureTopazShim.tabletPort",
+				"HID1"); // HID1 == "HSB" tablet HID port
+		s.configure(c);
+		System.out.println("Initializing shim driver");
+		s.init();
+		System.out.println("Initializing signature request for pad");
+		s.initJobRequest(null);
+	}
+
+}
diff --git a/shim-drivers/shim-driver-signature-topaz/test.sh b/shim-drivers/shim-driver-signature-topaz/test.sh
new file mode 100755
index 0000000..c60f81d
--- /dev/null
+++ b/shim-drivers/shim-driver-signature-topaz/test.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# $Id$
+#
+# Authors:
+#      Jeff Buchbinder <jeff at freemedsoftware.org>
+#
+# FreeMED Electronic Medical Record and Practice Management System
+# Copyright (C) 1999-2012 FreeMED Software Foundation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+
+# Test script for Topaz driver
+
+P="$( cd "$(dirname "$0")" ; pwd )"
+JDK_LOCATION="/usr/lib/jvm/jdk1.6.0_21"
+JNI_PLATFORM=i686-unknown-linux-gnu
+
+${JDK_LOCATION}/jre/bin/java -Djava.library.path=native/${JNI_PLATFORM} -cp $P/target/classes:$P/../../shim-library/target/classes:$P/deps/commapi-2.0.3.jar:$P/deps/sigplus-2.60:${HOME}/.m2/repository/log4j/log4j/1.2.16/log4j-1.2.16.jar:${HOME}/.m2/repository/org/tmatesoft/sqljet/sqljet/1.0.3/sqljet-1.0.3.jar org.freemedsoftware.device.impl.SignatureTopazShim
+
diff --git a/shim-library/.classpath b/shim-library/.classpath
new file mode 100644
index 0000000..8a3cf79
--- /dev/null
+++ b/shim-library/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/shim-library/.project b/shim-library/.project
new file mode 100644
index 0000000..b05c6d9
--- /dev/null
+++ b/shim-library/.project
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>shim-library</name>
+	<comment>NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse.</comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+	</natures>
+</projectDescription>
diff --git a/shim-library/.settings/org.eclipse.jdt.core.prefs b/shim-library/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..c6db809
--- /dev/null
+++ b/shim-library/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,13 @@
+#Fri Aug 13 15:37:38 EDT 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/shim-library/.settings/org.eclipse.wst.common.component b/shim-library/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..44bf0a0
--- /dev/null
+++ b/shim-library/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="shim-library">
+        <wb-resource deploy-path="/" source-path="/src/main/java"/>
+    </wb-module>
+</project-modules>
diff --git a/shim-library/.settings/org.eclipse.wst.common.project.facet.core.xml b/shim-library/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..f68988c
--- /dev/null
+++ b/shim-library/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="jst.java" version="6.0"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/shim-library/.settings/org.maven.ide.eclipse.prefs b/shim-library/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..ec8e7f7
--- /dev/null
+++ b/shim-library/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Fri Jul 30 13:06:04 EDT 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/shim-library/deps/extcos-0.1.1b.jar b/shim-library/deps/extcos-0.1.1b.jar
new file mode 100644
index 0000000..9e7b7b8
Binary files /dev/null and b/shim-library/deps/extcos-0.1.1b.jar differ
diff --git a/shim-library/deps/extcos-0.1b.jar b/shim-library/deps/extcos-0.1b.jar
new file mode 100644
index 0000000..bad0ad6
Binary files /dev/null and b/shim-library/deps/extcos-0.1b.jar differ
diff --git a/shim-library/deps/rxtx-2.2pre2.jar b/shim-library/deps/rxtx-2.2pre2.jar
new file mode 100644
index 0000000..afb4b16
Binary files /dev/null and b/shim-library/deps/rxtx-2.2pre2.jar differ
diff --git a/shim-library/native/i686-unknown-linux-gnu/librxtxParallel.so b/shim-library/native/i686-unknown-linux-gnu/librxtxParallel.so
new file mode 100755
index 0000000..476313f
Binary files /dev/null and b/shim-library/native/i686-unknown-linux-gnu/librxtxParallel.so differ
diff --git a/shim-library/native/i686-unknown-linux-gnu/librxtxSerial.so b/shim-library/native/i686-unknown-linux-gnu/librxtxSerial.so
new file mode 100755
index 0000000..e60c5e6
Binary files /dev/null and b/shim-library/native/i686-unknown-linux-gnu/librxtxSerial.so differ
diff --git a/shim-library/native/ia64-unknown-linux-gnu/librxtxSerial.so b/shim-library/native/ia64-unknown-linux-gnu/librxtxSerial.so
new file mode 100755
index 0000000..916db00
Binary files /dev/null and b/shim-library/native/ia64-unknown-linux-gnu/librxtxSerial.so differ
diff --git a/shim-library/native/win32/rxtxSerial.dll b/shim-library/native/win32/rxtxSerial.dll
new file mode 100755
index 0000000..c5ae7a7
Binary files /dev/null and b/shim-library/native/win32/rxtxSerial.dll differ
diff --git a/shim-library/native/win64/rxtxSerial.dll b/shim-library/native/win64/rxtxSerial.dll
new file mode 100755
index 0000000..262da15
Binary files /dev/null and b/shim-library/native/win64/rxtxSerial.dll differ
diff --git a/shim-library/native/x86_64-unknown-linux-gnu/librxtxParallel.so b/shim-library/native/x86_64-unknown-linux-gnu/librxtxParallel.so
new file mode 100755
index 0000000..b472159
Binary files /dev/null and b/shim-library/native/x86_64-unknown-linux-gnu/librxtxParallel.so differ
diff --git a/shim-library/native/x86_64-unknown-linux-gnu/librxtxSerial.so b/shim-library/native/x86_64-unknown-linux-gnu/librxtxSerial.so
new file mode 100755
index 0000000..1bb7949
Binary files /dev/null and b/shim-library/native/x86_64-unknown-linux-gnu/librxtxSerial.so differ
diff --git a/shim-library/pom.xml b/shim-library/pom.xml
new file mode 100644
index 0000000..93f71ff
--- /dev/null
+++ b/shim-library/pom.xml
@@ -0,0 +1,122 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<groupId>org.freemedsoftware</groupId>
+	<artifactId>shim-library</artifactId>
+	<version>0.1.1</version>
+	<packaging>jar</packaging>
+
+	<name>shim-library</name>
+	<url>http://freemedsoftware.org</url>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+	</properties>
+
+	<dependencies>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.8.2</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>log4j</groupId>
+			<artifactId>log4j</artifactId>
+			<version>1.2.16</version>
+			<type>jar</type>
+			<scope>compile</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.hsqldb</groupId>
+			<artifactId>hsqldb</artifactId>
+			<version>2.2.8</version>
+			<type>jar</type>
+			<scope>compile</scope>
+		</dependency>
+		<dependency>
+			<groupId>commons-logging</groupId>
+			<artifactId>commons-logging</artifactId>
+			<version>1.1.1</version>
+			<type>jar</type>
+			<scope>compile</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.reflections</groupId>
+			<artifactId>reflections</artifactId>
+			<version>0.9.5-RC2</version>
+		</dependency>
+		<dependency>
+			<groupId>org.rxtx</groupId>
+			<artifactId>rxtx</artifactId>
+			<version>2.2pre2</version>
+			<type>jar</type>
+			<scope>system</scope>
+			<systemPath>${basedir}/deps/rxtx-2.2pre2.jar</systemPath>
+		</dependency>
+		<dependency>
+			<groupId>org.tmatesoft.sqljet</groupId>
+			<artifactId>sqljet</artifactId>
+			<version>1.0.4</version>
+			<scope>compile</scope>
+		</dependency>
+		<dependency>
+			<groupId>com.google.code.gson</groupId>
+			<artifactId>gson</artifactId>
+			<version>1.7.1</version>
+			<type>jar</type>
+			<scope>compile</scope>
+		</dependency>
+	</dependencies>
+
+	<reporting>
+		<plugins>
+			<!-- Build javadocs for this project -->
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+				<version>2.8</version>
+				<configuration>
+				</configuration>
+			</plugin>
+		</plugins>
+	</reporting>
+
+	<build>
+		<plugins>
+			<!-- Compile -->
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>2.3.2</version>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+
+			<!-- Build javadocs for this project -->
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+				<version>2.8</version>
+				<configuration>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+	<repositories>
+		<repository>
+			<id>reflections-repo</id>
+			<name>Reflections Maven2 Repository</name>
+			<url>http://reflections.googlecode.com/svn/repo</url>
+		</repository>
+		<repository>
+			<id>tmate</id>
+			<url>http://maven.svnkit.com/maven2</url>
+		</repository>
+	</repositories>
+
+</project>
diff --git a/shim-library/src/main/java/org/freemedsoftware/device/DeviceCapability.java b/shim-library/src/main/java/org/freemedsoftware/device/DeviceCapability.java
new file mode 100644
index 0000000..7b95d64
--- /dev/null
+++ b/shim-library/src/main/java/org/freemedsoftware/device/DeviceCapability.java
@@ -0,0 +1,42 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device;
+
+public enum DeviceCapability {
+	DEVICE_SIGNATURE_TABLET("DEVICE_SIGNATURE_TABLET"), DEVICE_VITAL_SIGNS(
+			"DEVICE_VITAL_SIGNS"), DEVICE_LABEL_PRINTER("DEVICE_LABEL_PRINTER"), DEVICE_DOSING_PUMP(
+			"DEVICE_DOSING_PUMP");
+
+	private String txt = null;
+
+	DeviceCapability(String txt) {
+		this.txt = txt;
+	}
+
+	@Override
+	public String toString() {
+		return this.txt;
+	}
+}
diff --git a/shim-library/src/main/java/org/freemedsoftware/device/DeviceInterface.java b/shim-library/src/main/java/org/freemedsoftware/device/DeviceInterface.java
new file mode 100644
index 0000000..df8bb9d
--- /dev/null
+++ b/shim-library/src/main/java/org/freemedsoftware/device/DeviceInterface.java
@@ -0,0 +1,52 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device;
+
+import java.util.HashMap;
+import java.util.List;
+
+public interface DeviceInterface {
+
+	public void configure(HashMap<String, Object> config);
+
+	public List<String> getConfigurationOptions();
+
+	public void init() throws Exception;
+
+	public void close() throws Exception;
+
+	public boolean isProcessing();
+
+	/**
+	 * Initialize request for a job on a device.
+	 * 
+	 * @param item
+	 *            <JobStoreItem> object for this job.
+	 * @return Success
+	 * @throws Exception
+	 */
+	public boolean initJobRequest(JobStoreItem item) throws Exception;
+
+}
diff --git a/shim-library/src/main/java/org/freemedsoftware/device/DosingPumpCommand.java b/shim-library/src/main/java/org/freemedsoftware/device/DosingPumpCommand.java
new file mode 100644
index 0000000..a02555e
--- /dev/null
+++ b/shim-library/src/main/java/org/freemedsoftware/device/DosingPumpCommand.java
@@ -0,0 +1,41 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device;
+
+public enum DosingPumpCommand {
+	DISPENSE("DISPENSE"), PRIME("PRIME"), GET_STATUS("GET_STATUS"), REVERSE(
+			"REVERSE");
+
+	private String txt = null;
+
+	DosingPumpCommand(String txt) {
+		this.txt = txt;
+	}
+
+	@Override
+	public String toString() {
+		return this.txt;
+	}
+}
diff --git a/shim-library/src/main/java/org/freemedsoftware/device/DosingPumpInterface.java b/shim-library/src/main/java/org/freemedsoftware/device/DosingPumpInterface.java
new file mode 100644
index 0000000..6299d76
--- /dev/null
+++ b/shim-library/src/main/java/org/freemedsoftware/device/DosingPumpInterface.java
@@ -0,0 +1,43 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device;
+
+/**
+ * <DeviceInterface> child interface. All dosing pump devices should implement
+ * this interface.
+ * 
+ * @author jeff at freemedsoftware.org
+ */
+public interface DosingPumpInterface extends DeviceInterface {
+
+	public String primePump() throws Exception;
+
+	public String reversePump() throws Exception;
+
+	public String getPumpStatus() throws Exception;
+
+	public String dispenseDose(Integer units) throws Exception;
+
+}
diff --git a/shim-library/src/main/java/org/freemedsoftware/device/DosingPumpSerialInterface.java b/shim-library/src/main/java/org/freemedsoftware/device/DosingPumpSerialInterface.java
new file mode 100644
index 0000000..a218dc6
--- /dev/null
+++ b/shim-library/src/main/java/org/freemedsoftware/device/DosingPumpSerialInterface.java
@@ -0,0 +1,146 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device;
+
+import gnu.io.CommPortIdentifier;
+import gnu.io.NoSuchPortException;
+import gnu.io.PortInUseException;
+import gnu.io.UnsupportedCommOperationException;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.log4j.Logger;
+
+public abstract class DosingPumpSerialInterface implements DosingPumpInterface {
+
+	protected Logger log = Logger.getLogger(DosingPumpSerialInterface.class);
+
+	protected HashMap<String, Object> config = new HashMap<String, Object>();
+
+	protected AtomicBoolean processing = new AtomicBoolean();
+
+	protected SerialInterface serialInterface = null;
+
+	protected String configName = null;
+
+	public String getConfigName() {
+		return this.configName;
+	}
+
+	public void setConfigName(String configName) {
+		this.configName = configName;
+	}
+
+	@Override
+	public void close() throws Exception {
+		if (serialInterface != null) {
+			log.info("Closing serial port for dosing pump");
+			serialInterface.close();
+		}
+	}
+
+	@Override
+	public void configure(HashMap<String, Object> config) {
+		this.config = config;
+	}
+
+	@Override
+	public List<String> getConfigurationOptions() {
+		return Arrays.asList(new String[] { getConfigName() + ".enabled",
+				getConfigName() + ".port", getConfigName() + ".baud",
+				getConfigName() + ".timeout" });
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public void init() throws Exception {
+		// Initially, set to "processing" so we don't have pigpiles.
+		processing.set(true);
+
+		if (config.get(getConfigName() + ".enabled").equals("false")) {
+			throw new Exception("Skipping dosing pump, " + getConfigName()
+					+ ".enabled=false");
+		}
+
+		// Display available ports
+		log.info("Scanning for available ports");
+		Enumeration portList = (Enumeration) CommPortIdentifier
+				.getPortIdentifiers();
+		while (portList.hasMoreElements()) {
+			CommPortIdentifier portId = (CommPortIdentifier) portList
+					.nextElement();
+			if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
+				log.debug("Found port: " + portId.getName());
+			}
+		}
+
+		serialInterface = new SerialInterface();
+		log
+				.info("opening pump.port = "
+						+ config.get(getConfigName() + ".port"));
+		try {
+			serialInterface.open(
+					(String) config.get(getConfigName() + ".port"), Integer
+							.parseInt((String) config.get(getConfigName()
+									+ ".baud")), Integer
+							.parseInt((String) config.get(getConfigName()
+									+ ".timeout")));
+		} catch (NoSuchPortException e) {
+			log.error(e);
+			throw e;
+		} catch (PortInUseException e) {
+			log.error(e);
+			throw e;
+		} catch (UnsupportedCommOperationException e) {
+			log.error(e);
+			throw e;
+		} catch (IOException e) {
+			log.error(e);
+			throw e;
+		}
+		log.info("Pump opened");
+
+		// Unlock when we're ready to go.
+		processing.set(false);
+	}
+
+	@Override
+	public boolean initJobRequest(JobStoreItem item) throws Exception {
+		log
+				.warn("Currently unused (initJobRequest), as communication is synchronous");
+		return false;
+	}
+
+	@Override
+	public boolean isProcessing() {
+		return processing.get();
+	}
+
+}
diff --git a/shim-library/src/main/java/org/freemedsoftware/device/JobStoreItem.java b/shim-library/src/main/java/org/freemedsoftware/device/JobStoreItem.java
new file mode 100644
index 0000000..08b29ee
--- /dev/null
+++ b/shim-library/src/main/java/org/freemedsoftware/device/JobStoreItem.java
@@ -0,0 +1,145 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device;
+
+import java.util.HashMap;
+
+public class JobStoreItem {
+
+	/**
+	 * Status for completed jobs.
+	 */
+	public final static String STATUS_COMPLETED = "COMPLETE";
+
+	/**
+	 * Status for jobs which have run but returned errors.
+	 */
+	public final static String STATUS_ERROR = "ERROR";
+
+	/**
+	 * Status for jobs which are currently being processed.
+	 */
+	public final static String STATUS_PENDING = "PENDING";
+
+	/**
+	 * Status for unassigned jobs.
+	 */
+	public final static String STATUS_NEW = "NEW";
+
+	public final static String DEVICE_LABEL = "LABEL";
+	public final static String DEVICE_SIGNATURE = "SIGNATURE";
+	public final static String DEVICE_VITALS = "VITALS";
+
+	private Integer id;
+
+	private String status;
+
+	private String device;
+
+	private String displayText;
+
+	private String printTemplate = null;
+
+	private HashMap<String, String> printParameters = new HashMap<String, String>();
+
+	private Integer printCount = 1;
+
+	private byte[] signatureRaw;
+
+	private byte[] signatureImage;
+
+	public void setId(Integer id) {
+		this.id = id;
+	}
+
+	public Integer getId() {
+		return id;
+	}
+
+	public void setDevice(String device) {
+		this.device = device;
+	}
+
+	public String getDevice() {
+		return device;
+	}
+
+	public void setStatus(String status) {
+		this.status = status;
+	}
+
+	public String getStatus() {
+		return status;
+	}
+
+	public void setDisplayText(String displayText) {
+		this.displayText = displayText;
+	}
+
+	public String getDisplayText() {
+		return displayText;
+	}
+
+	public void setPrintTemplate(String printTemplate) {
+		this.printTemplate = printTemplate;
+	}
+
+	public String getPrintTemplate() {
+		return printTemplate;
+	}
+
+	public void setPrintParameters(HashMap<String, String> printParameters) {
+		this.printParameters = printParameters;
+	}
+
+	public HashMap<String, String> getPrintParameters() {
+		return printParameters;
+	}
+
+	public void setPrintCount(Integer printCount) {
+		this.printCount = printCount;
+	}
+
+	public Integer getPrintCount() {
+		return printCount;
+	}
+
+	public void setSignatureRaw(byte[] signatureRaw) {
+		this.signatureRaw = signatureRaw;
+	}
+
+	public byte[] getSignatureRaw() {
+		return signatureRaw;
+	}
+
+	public void setSignatureImage(byte[] signatureImage) {
+		this.signatureImage = signatureImage;
+	}
+
+	public byte[] getSignatureImage() {
+		return signatureImage;
+	}
+
+}
diff --git a/shim-library/src/main/java/org/freemedsoftware/device/LabSerialInterface.java b/shim-library/src/main/java/org/freemedsoftware/device/LabSerialInterface.java
new file mode 100644
index 0000000..5668569
--- /dev/null
+++ b/shim-library/src/main/java/org/freemedsoftware/device/LabSerialInterface.java
@@ -0,0 +1,146 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device;
+
+import gnu.io.CommPortIdentifier;
+import gnu.io.NoSuchPortException;
+import gnu.io.PortInUseException;
+import gnu.io.UnsupportedCommOperationException;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.log4j.Logger;
+
+public abstract class LabSerialInterface implements DeviceInterface {
+
+	protected Logger log = Logger.getLogger(LabSerialInterface.class);
+
+	protected HashMap<String, Object> config = new HashMap<String, Object>();
+
+	protected AtomicBoolean processing = new AtomicBoolean();
+
+	protected SerialInterface serialInterface = null;
+
+	protected String configName = null;
+
+	public String getConfigName() {
+		return this.configName;
+	}
+
+	public void setConfigName(String configName) {
+		this.configName = configName;
+	}
+
+	@Override
+	public void close() throws Exception {
+		if (serialInterface != null) {
+			log.info("Closing serial port for lab device");
+			serialInterface.close();
+		}
+	}
+
+	@Override
+	public void configure(HashMap<String, Object> config) {
+		this.config = config;
+	}
+
+	@Override
+	public List<String> getConfigurationOptions() {
+		return Arrays.asList(new String[] { getConfigName() + ".enabled",
+				getConfigName() + ".port", getConfigName() + ".baud",
+				getConfigName() + ".timeout" });
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public void init() throws Exception {
+		// Initially, set to "processing" so we don't have pigpiles.
+		processing.set(true);
+
+		if (config.get(getConfigName() + ".enabled").equals("false")) {
+			throw new Exception("Skipping lab, " + getConfigName()
+					+ ".enabled=false");
+		}
+
+		// Display available ports
+		log.info("Scanning for available ports");
+		Enumeration portList = (Enumeration) CommPortIdentifier
+				.getPortIdentifiers();
+		while (portList.hasMoreElements()) {
+			CommPortIdentifier portId = (CommPortIdentifier) portList
+					.nextElement();
+			if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
+				log.debug("Found port: " + portId.getName());
+			}
+		}
+
+		serialInterface = new SerialInterface();
+		log
+				.info("opening pump.port = "
+						+ config.get(getConfigName() + ".port"));
+		try {
+			serialInterface.open(
+					(String) config.get(getConfigName() + ".port"), Integer
+							.parseInt((String) config.get(getConfigName()
+									+ ".baud")), Integer
+							.parseInt((String) config.get(getConfigName()
+									+ ".timeout")));
+		} catch (NoSuchPortException e) {
+			log.error(e);
+			throw e;
+		} catch (PortInUseException e) {
+			log.error(e);
+			throw e;
+		} catch (UnsupportedCommOperationException e) {
+			log.error(e);
+			throw e;
+		} catch (IOException e) {
+			log.error(e);
+			throw e;
+		}
+		log.info("Lab device opened");
+
+		// Unlock when we're ready to go.
+		processing.set(false);
+	}
+
+	@Override
+	public boolean initJobRequest(JobStoreItem item) throws Exception {
+		log
+				.warn("Currently unused (initJobRequest), as communication is synchronous");
+		return false;
+	}
+
+	@Override
+	public boolean isProcessing() {
+		return processing.get();
+	}
+
+}
diff --git a/shim-library/src/main/java/org/freemedsoftware/device/LabelPrinterInterface.java b/shim-library/src/main/java/org/freemedsoftware/device/LabelPrinterInterface.java
new file mode 100644
index 0000000..56cf323
--- /dev/null
+++ b/shim-library/src/main/java/org/freemedsoftware/device/LabelPrinterInterface.java
@@ -0,0 +1,39 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device;
+
+import java.io.IOException;
+
+/**
+ * <DeviceInterface> child interface. All label printer devices should implement
+ * this interface.
+ * 
+ * @author jeff at freemedsoftware.org
+ */
+public interface LabelPrinterInterface extends DeviceInterface {
+
+	public boolean writeToPrinter(byte[] data) throws IOException;
+
+}
diff --git a/shim-library/src/main/java/org/freemedsoftware/device/ParallelPrinterInterface.java b/shim-library/src/main/java/org/freemedsoftware/device/ParallelPrinterInterface.java
new file mode 100644
index 0000000..2a8b509
--- /dev/null
+++ b/shim-library/src/main/java/org/freemedsoftware/device/ParallelPrinterInterface.java
@@ -0,0 +1,121 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device;
+
+import gnu.io.CommPortIdentifier;
+import gnu.io.CommPortOwnershipListener;
+import gnu.io.NoSuchPortException;
+import gnu.io.ParallelPort;
+import gnu.io.PortInUseException;
+import gnu.io.UnsupportedCommOperationException;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.log4j.Logger;
+
+public class ParallelPrinterInterface implements CommPortOwnershipListener,
+		Runnable {
+
+	public enum PortStatus {
+		OPEN, CLOSED, ERROR
+	};
+
+	static final Logger log = Logger.getLogger(ParallelPrinterInterface.class);
+
+	protected OutputStream out = null;
+	protected ParallelPort parallelPort = null;
+	protected PortStatus portStatus = PortStatus.CLOSED;
+
+	public ParallelPrinterInterface() {
+	}
+
+	public void open(String portName, int timeout) throws NoSuchPortException,
+			PortInUseException, UnsupportedCommOperationException, IOException {
+		if (portStatus != PortStatus.OPEN) {
+			CommPortIdentifier portId = CommPortIdentifier
+					.getPortIdentifier(portName);
+			portId.addPortOwnershipListener(this);
+			parallelPort = (ParallelPort) portId.open("Parallel", timeout);
+			parallelPort.setMode(ParallelPort.LPT_MODE_ANY);
+			out = parallelPort.getOutputStream();
+			portStatus = PortStatus.OPEN;
+		}
+	}
+
+	public OutputStream getOutputStream() {
+		return out;
+	}
+
+	public void write(String data) throws IOException {
+		log.info("Attempting write for " + data.length() + " bytes");
+		byte[] b = data.getBytes("ASCII");
+		for (int iter = 0; iter < b.length; iter++) {
+			log.trace("Pushing byte #" + iter + " (" + b[iter] + ")");
+			out.write(b[iter]);
+		}
+		out.flush();
+	}
+
+	public void close() {
+		if (portStatus == PortStatus.OPEN) {
+			portStatus = PortStatus.CLOSED;
+			try {
+				out.close();
+			} catch (IOException ex) {
+			}
+		}
+	}
+
+	@Override
+	public void ownershipChange(int type) {
+		switch (type) {
+		case CommPortOwnershipListener.PORT_OWNED:
+			log.info("We got the port");
+			break;
+		case CommPortOwnershipListener.PORT_UNOWNED:
+			log.info("We've just lost our port ownership");
+			break;
+		case CommPortOwnershipListener.PORT_OWNERSHIP_REQUESTED:
+			log.info("Someone is asking our port's ownership");
+			break;
+		}
+	}
+
+	@Override
+	public void run() {
+		// TODO: open
+		while (true) {
+			try {
+				Thread.sleep(1000);
+			} catch (InterruptedException e) {
+				log.warn(e);
+				// TODO: close
+				log.info("Exiting child thread.");
+			}
+		}
+	}
+
+}
diff --git a/shim-library/src/main/java/org/freemedsoftware/device/PersistentJobStore.java b/shim-library/src/main/java/org/freemedsoftware/device/PersistentJobStore.java
new file mode 100644
index 0000000..4812589
--- /dev/null
+++ b/shim-library/src/main/java/org/freemedsoftware/device/PersistentJobStore.java
@@ -0,0 +1,43 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device;
+
+import org.apache.log4j.Logger;
+
+public class PersistentJobStore {
+
+	protected static Logger log = Logger.getLogger(PersistentJobStore.class);
+
+	private String dbLocation = null;
+
+	protected String getDbLocation() {
+		return this.dbLocation;
+	}
+
+	public void setDbLocation(String dbLocation) {
+		this.dbLocation = dbLocation;
+	}
+
+}
diff --git a/shim-library/src/main/java/org/freemedsoftware/device/PersistentJobStoreDAO.java b/shim-library/src/main/java/org/freemedsoftware/device/PersistentJobStoreDAO.java
new file mode 100644
index 0000000..768b590
--- /dev/null
+++ b/shim-library/src/main/java/org/freemedsoftware/device/PersistentJobStoreDAO.java
@@ -0,0 +1,280 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.tmatesoft.sqljet.core.SqlJetException;
+import org.tmatesoft.sqljet.core.SqlJetTransactionMode;
+import org.tmatesoft.sqljet.core.table.ISqlJetCursor;
+import org.tmatesoft.sqljet.core.table.ISqlJetTable;
+import org.tmatesoft.sqljet.core.table.SqlJetDb;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
+public class PersistentJobStoreDAO {
+
+	static final Logger log = Logger.getLogger(PersistentJobStoreDAO.class);
+
+	protected static SqlJetDb db = null;
+
+	private static final String TABLE_NAME = "jobstore";
+
+	private static final String JOB_STORE_CREATE_SQL = "CREATE TABLE "
+			+ TABLE_NAME + " ( " + " id INTEGER NOT NULL PRIMARY KEY"
+			+ " , device TEXT NOT NULL " + " , status TEXT NOT NULL "
+			+ " , displayText TEXT " + " , printTemplate TEXT "
+			+ " , printParameters TEXT "
+			+ " , printCount INT NOT NULL DEFAULT 1 " + " , sigraw BLOB "
+			+ " , sigimage BLOB " + " ) ; ";
+
+	private static final String JOB_STORE_INDEX_ID_SQL = "CREATE INDEX id_index ON "
+			+ TABLE_NAME + "(id)";
+
+	private static final String JOB_STORE_INDEX_STATUS_SQL = "CREATE INDEX status_index ON "
+			+ TABLE_NAME + "(status)";
+
+	public static void open(String fileName) throws SqlJetException {
+		db = SqlJetDb.open(new File(fileName), true);
+		db.beginTransaction(SqlJetTransactionMode.WRITE);
+		try {
+			db.getOptions().setUserVersion(1);
+		} catch (Throwable t) {
+			log.error(t);
+			throw new SqlJetException(t);
+		} finally {
+			db.commit();
+		}
+	}
+
+	public static void create(String fileName) throws SqlJetException {
+		File dbFile = new File(fileName);
+		dbFile.delete();
+
+		db = SqlJetDb.open(dbFile, true);
+		db.getOptions().setAutovacuum(true);
+		db.beginTransaction(SqlJetTransactionMode.WRITE);
+		try {
+			db.getOptions().setUserVersion(1);
+		} catch (Throwable t) {
+			log.error(t);
+			throw new SqlJetException(t);
+		} finally {
+			db.commit();
+		}
+
+		db.beginTransaction(SqlJetTransactionMode.WRITE);
+		try {
+			db.createTable(JOB_STORE_CREATE_SQL);
+			db.createIndex(JOB_STORE_INDEX_ID_SQL);
+			db.createIndex(JOB_STORE_INDEX_STATUS_SQL);
+		} catch (Throwable t) {
+			log.error(t);
+			throw new SqlJetException(t);
+		} finally {
+			db.commit();
+		}
+	}
+
+	public static void delete(Integer id) throws SqlJetException {
+		synchronized (db) {
+			db.beginTransaction(SqlJetTransactionMode.WRITE);
+			try {
+				ISqlJetTable table = db.getTable(TABLE_NAME);
+				ISqlJetCursor deleteCursor = table.scope(table
+						.getPrimaryKeyIndexName(), new Object[] { id },
+						new Object[] { id });
+				while (!deleteCursor.eof()) {
+					if (deleteCursor.getInteger("id") == id) {
+						deleteCursor.delete();
+					}
+				}
+				deleteCursor.close();
+			} catch (Throwable t) {
+				log.error(t);
+				throw new SqlJetException(t);
+			} finally {
+				db.commit();
+			}
+		}
+	}
+
+	public static JobStoreItem get(Integer id) throws SqlJetException {
+		synchronized (db) {
+			db.beginTransaction(SqlJetTransactionMode.READ_ONLY);
+			try {
+				ISqlJetTable table = db.getTable(TABLE_NAME);
+				ISqlJetCursor cursor = table.lookup("id_index", id);
+
+				JobStoreItem item = new JobStoreItem();
+				item.setId(id);
+				item.setDevice(cursor.getString("device"));
+				item.setStatus(cursor.getString("status"));
+				item.setDisplayText(cursor.getString("displayText"));
+				item.setPrintTemplate(cursor.getString("printTemplate"));
+				item.setPrintParameters(deserializeMap(cursor
+						.getString("printParameters")));
+				item.setPrintCount((int) cursor.getInteger("printCount"));
+				item.setSignatureRaw(cursor.getBlobAsArray("sigraw"));
+				item.setSignatureImage(cursor.getBlobAsArray("sigimage"));
+
+				cursor.close();
+
+				return item;
+			} catch (Throwable t) {
+				log.error(t);
+				throw new SqlJetException(t);
+			} finally {
+				db.commit();
+			}
+		}
+	}
+
+	public static List<JobStoreItem> unassignedJobs() throws SqlJetException {
+		synchronized (db) {
+			db.beginTransaction(SqlJetTransactionMode.READ_ONLY);
+			try {
+				ISqlJetTable table = db.getTable(TABLE_NAME);
+				ISqlJetCursor cursor = table.lookup("status_index",
+						JobStoreItem.STATUS_NEW);
+
+				List<JobStoreItem> items = new ArrayList<JobStoreItem>();
+				if (cursor.getRowCount() < 1) {
+					return items;
+				}
+
+				do {
+					JobStoreItem item = new JobStoreItem();
+					item.setId((int) cursor.getInteger("id"));
+					item.setDevice(cursor.getString("device"));
+					item.setStatus(cursor.getString("status"));
+					item.setDisplayText(cursor.getString("displayText"));
+					item.setPrintTemplate(cursor.getString("printTemplate"));
+					item.setPrintParameters(deserializeMap(cursor
+							.getString("printParameters")));
+					item.setPrintCount((int) cursor.getInteger("printCount"));
+					item.setSignatureRaw(cursor.getBlobAsArray("sigraw"));
+					item.setSignatureImage(cursor.getBlobAsArray("sigimage"));
+					items.add(item);
+				} while (cursor.next());
+
+				cursor.close();
+
+				return items;
+			} catch (Throwable t) {
+				log.debug(t);
+				throw new SqlJetException(t);
+			} finally {
+				db.commit();
+			}
+		}
+	}
+
+	public static int insert(JobStoreItem i) throws SqlJetException {
+		synchronized (db) {
+			db.beginTransaction(SqlJetTransactionMode.WRITE);
+			try {
+				ISqlJetTable table = db.getTable(TABLE_NAME);
+				return (int) table.insert(i.getId(), i.getDevice(), i
+						.getStatus(), i.getDisplayText(), i.getPrintTemplate(),
+						serializeMap(i.getPrintParameters()),
+						i.getPrintCount(), i.getSignatureRaw(), i
+								.getSignatureImage());
+			} catch (Exception t) {
+				log.error(t);
+				throw new SqlJetException(t);
+			} finally {
+				db.commit();
+			}
+		}
+	}
+
+	public static void update(JobStoreItem i) throws SqlJetException {
+		synchronized (db) {
+			db.beginTransaction(SqlJetTransactionMode.WRITE);
+			try {
+				ISqlJetTable table = db.getTable(TABLE_NAME);
+				ISqlJetCursor updateCursor = table.scope(table
+						.getPrimaryKeyIndexName(), new Object[] { i.getId() },
+						new Object[] { i.getId() });
+				do {
+					if (updateCursor.getInteger("id") == i.getId()) {
+						updateCursor.update(i.getId(), i.getDevice(), i
+								.getStatus(), i.getDisplayText(), i
+								.getPrintTemplate(), serializeMap(i
+								.getPrintParameters()), i.getPrintCount(), i
+								.getSignatureRaw(), i.getSignatureImage());
+					}
+				} while (updateCursor.next());
+				updateCursor.close();
+			} catch (Throwable t) {
+				log.error(t);
+				throw new SqlJetException(t);
+			} finally {
+				db.commit();
+			}
+		}
+	}
+
+	public static void close() {
+		if (db != null) {
+			try {
+				db.close();
+			} catch (SqlJetException e) {
+				log.error(e);
+			}
+		}
+	}
+
+	private static String serializeMap(HashMap<String, String> map) {
+		try {
+			return new Gson().toJson(map);
+		} catch (Exception ex) {
+			log.debug(ex);
+			return "{}";
+		}
+	}
+
+	@SuppressWarnings("unchecked")
+	private static HashMap<String, String> deserializeMap(String raw) {
+		try {
+			if (raw == null || raw == "" || raw == "{}") {
+				return (HashMap<String, String>) null;
+			}
+			return (HashMap<String, String>) new Gson().fromJson(raw,
+					new TypeToken<HashMap<String, String>>() {
+					}.getType());
+		} catch (Exception e) {
+			log.debug(e);
+			return (HashMap<String, String>) null;
+		}
+	}
+
+}
diff --git a/shim-library/src/main/java/org/freemedsoftware/device/SerialInterface.java b/shim-library/src/main/java/org/freemedsoftware/device/SerialInterface.java
new file mode 100644
index 0000000..22cbf6e
--- /dev/null
+++ b/shim-library/src/main/java/org/freemedsoftware/device/SerialInterface.java
@@ -0,0 +1,137 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device;
+
+import gnu.io.CommPortIdentifier;
+import gnu.io.NoSuchPortException;
+import gnu.io.PortInUseException;
+import gnu.io.SerialPort;
+import gnu.io.UnsupportedCommOperationException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.log4j.Logger;
+
+public class SerialInterface {
+
+	static final Logger log = Logger.getLogger(SerialInterface.class);
+
+	public enum PortStatus {
+		OPEN, CLOSED, ERROR
+	};
+
+	protected InputStream in = null;
+	protected OutputStream out = null;
+	protected SerialPort serialPort = null;
+	protected PortStatus portStatus = PortStatus.CLOSED;
+
+	public static char LF = 0x0a;
+	public static char CR = 0x0d;
+
+	public SerialInterface() {
+		log.info("Initializing ...");
+	}
+
+	public void open(String portName, int baud, int timeout)
+			throws NoSuchPortException, PortInUseException,
+			UnsupportedCommOperationException, IOException {
+		log.info("open() : " + portName + "/" + baud);
+		CommPortIdentifier portId = CommPortIdentifier
+				.getPortIdentifier(portName);
+		log.info("Attempting to open " + portId.getName());
+		serialPort = (SerialPort) portId.open("Serial", timeout);
+		serialPort.setSerialPortParams(baud, SerialPort.DATABITS_8,
+				SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
+		serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
+		serialPort.enableReceiveThreshold(1);
+		serialPort.enableReceiveTimeout(timeout);
+		out = serialPort.getOutputStream();
+		in = serialPort.getInputStream();
+		portStatus = PortStatus.OPEN;
+	}
+
+	public void write(String data) throws IOException {
+		byte[] content = data.getBytes();
+		int readCount = 0;
+		for (int iter = 0; iter < content.length; iter++) {
+			// Write out the content
+			out.write(content[iter]);
+			readCount++;
+		}
+
+		// End of line CR
+		out.write(CR);
+		readCount++;
+
+		for (int iter = 0; iter < readCount; iter++) {
+			int ch = in.read();
+			if (ch == -1) {
+				return;
+			} else {
+				log.info("during write, read echo char " + ch + " ("
+						+ (char) ch + ")");
+			}
+		}
+	}
+
+	public String read() throws IOException {
+		String o = new String();
+		int b = -1;
+		b = in.read();
+		while (b != -1) {
+			log.info("read() got character " + b + "(" + (char) b + ")");
+			o += (char) b;
+			b = in.read();
+		}
+		return o;
+	}
+
+	public void close() {
+		if (portStatus == PortStatus.OPEN) {
+			portStatus = PortStatus.CLOSED;
+		}
+		try {
+			in.close();
+			out.close();
+			serialPort.close();
+		} catch (IOException ex) {
+		}
+	}
+
+	public InputStream getInputStream() {
+		return in;
+	}
+
+	public OutputStream getOutputStream() {
+		return out;
+	}
+
+	public SerialPort getSerialPort() {
+		return serialPort;
+	}
+
+}
diff --git a/shim-library/src/main/java/org/freemedsoftware/device/ShimDevice.java b/shim-library/src/main/java/org/freemedsoftware/device/ShimDevice.java
new file mode 100644
index 0000000..438dcc6
--- /dev/null
+++ b/shim-library/src/main/java/org/freemedsoftware/device/ShimDevice.java
@@ -0,0 +1,37 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface ShimDevice {
+
+	String name();
+
+	DeviceCapability capability();
+
+}
diff --git a/shim-library/src/main/java/org/freemedsoftware/device/ShimDeviceManager.java b/shim-library/src/main/java/org/freemedsoftware/device/ShimDeviceManager.java
new file mode 100644
index 0000000..6d43bc0
--- /dev/null
+++ b/shim-library/src/main/java/org/freemedsoftware/device/ShimDeviceManager.java
@@ -0,0 +1,190 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device;
+
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+import org.reflections.Reflections;
+import org.reflections.scanners.ResourcesScanner;
+import org.reflections.scanners.SubTypesScanner;
+import org.reflections.scanners.TypeAnnotationsScanner;
+import org.reflections.util.ClasspathHelper;
+import org.reflections.util.ConfigurationBuilder;
+import org.reflections.util.FilterBuilder;
+
+import com.google.common.base.Predicate;
+
+public class ShimDeviceManager<T extends DeviceInterface> implements Runnable {
+
+	protected static Logger log = Logger.getLogger(ShimDeviceManager.class);
+
+	protected T deviceInstance = null;
+
+	protected Thread persistentThread = null;
+
+	protected boolean active = false;
+
+	protected String className = null;
+
+	public ShimDeviceManager() throws InstantiationException,
+			IllegalAccessException, ClassNotFoundException {
+	}
+
+	public boolean getActive() {
+		return this.active;
+	}
+
+	public void setActive(boolean active) {
+		this.active = active;
+	}
+
+	public String getClassName() {
+		return this.className;
+	}
+
+	public void setClassName(String className) {
+		this.className = className;
+	}
+
+	@SuppressWarnings("unchecked")
+	public ShimDeviceManager(String className) throws InstantiationException,
+			IllegalAccessException, ClassNotFoundException {
+		if (className == null) {
+			throw new InstantiationException("no class name given");
+		}
+		setClassName(className);
+		deviceInstance = (T) Class.forName(className).newInstance();
+	}
+
+	public void scanShimDevices() {
+		Predicate<String> filter = new FilterBuilder()
+				.include("org.freemedsoftware.device.impl.*");
+
+		Reflections r = new Reflections(
+				new ConfigurationBuilder()
+						.filterInputsBy(
+								new FilterBuilder.Include(FilterBuilder
+										.prefix("org.freemedsoftware.device")))
+						.setUrls(
+								ClasspathHelper
+										.getUrlsForPackagePrefix("org.freemedsoftware.device"))
+						.setScanners(new SubTypesScanner(),
+								new TypeAnnotationsScanner(),
+								new ResourcesScanner()));
+		/*
+		 * Reflections r = new Reflections( new ConfigurationBuilder()
+		 * .filterInputsBy(filter) .setScanners( new
+		 * SubTypesScanner().filterResultsBy(filter), new
+		 * TypeAnnotationsScanner() .filterResultsBy(filter), new
+		 * FieldAnnotationsScanner() .filterResultsBy(filter), new
+		 * MethodAnnotationsScanner() .filterResultsBy(filter), new
+		 * ConvertersScanner().filterResultsBy(filter)) .setUrls(
+		 * ClasspathHelper
+		 * .getUrlsForPackagePrefix("org.freemedsoftware.device.impl")));
+		 */
+		Set<Class<?>> s = r.getTypesAnnotatedWith(ShimDevice.class);
+		System.out.println("scanShimDevices found " + s.size() + " entries");
+		for (Class<?> c : s) {
+			System.out.println("canonical name: " + c.getCanonicalName());
+		}
+	}
+
+	/**
+	 * Initialize child device.
+	 * 
+	 * @throws Exception
+	 */
+	public void init() throws Exception {
+		if (deviceInstance == null) {
+			throw new Exception("device not initialized");
+		}
+		if (deviceInstance instanceof SignatureInterface) {
+			initSignatureDevice();
+		}
+		if (deviceInstance instanceof LabelPrinterInterface) {
+			initLabelPrinterDevice();
+		}
+		if (deviceInstance instanceof DosingPumpInterface) {
+			initDosingDevice();
+		}
+
+		// Set active to true
+		setActive(true);
+	}
+
+	/**
+	 * Get internal device driver instance.
+	 * 
+	 * @return
+	 */
+	public T getDeviceInstance() {
+		return deviceInstance;
+	}
+
+	protected void initDosingDevice() throws Exception {
+		log.info("initDosingDevice()");
+		DosingPumpInterface sDevice = (DosingPumpInterface) deviceInstance;
+		log.info("Running device init");
+		sDevice.init();
+		persistentThread = new Thread(this);
+	}
+
+	protected void initSignatureDevice() throws Exception {
+		log.info("initSignatureDevice()");
+		SignatureInterface sDevice = (SignatureInterface) deviceInstance;
+		log.info("Running device init");
+		sDevice.init();
+		persistentThread = new Thread(this);
+	}
+
+	protected void initLabelPrinterDevice() throws Exception {
+		log.info("initSignatureDevice()");
+		LabelPrinterInterface lDevice = (LabelPrinterInterface) deviceInstance;
+		log.info("Running device init");
+		lDevice.init();
+		persistentThread = new Thread(this);
+	}
+
+	/**
+	 * Closes child device if open.
+	 * 
+	 * @throws Exception
+	 */
+	public void close() throws Exception {
+		if (deviceInstance != null) {
+			deviceInstance.close();
+		}
+		if (persistentThread != null) {
+			persistentThread.interrupt();
+		}
+		setActive(false);
+	}
+
+	@Override
+	public void run() {
+	}
+
+}
diff --git a/shim-library/src/main/java/org/freemedsoftware/device/SignatureInterface.java b/shim-library/src/main/java/org/freemedsoftware/device/SignatureInterface.java
new file mode 100644
index 0000000..3fa225f
--- /dev/null
+++ b/shim-library/src/main/java/org/freemedsoftware/device/SignatureInterface.java
@@ -0,0 +1,35 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device;
+
+/**
+ * <DeviceInterface> child interface. All signature pad devices should implement
+ * this interface.
+ * 
+ * @author jeff at freemedsoftware.org
+ */
+public interface SignatureInterface extends DeviceInterface {
+
+}
diff --git a/shim-library/src/main/java/org/freemedsoftware/device/impl/DummyShim.java b/shim-library/src/main/java/org/freemedsoftware/device/impl/DummyShim.java
new file mode 100644
index 0000000..8bcf667
--- /dev/null
+++ b/shim-library/src/main/java/org/freemedsoftware/device/impl/DummyShim.java
@@ -0,0 +1,68 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device.impl;
+
+import java.util.HashMap;
+import java.util.List;
+
+import org.freemedsoftware.device.DeviceCapability;
+import org.freemedsoftware.device.DeviceInterface;
+import org.freemedsoftware.device.JobStoreItem;
+import org.freemedsoftware.device.ShimDevice;
+
+ at ShimDevice(name = "Dummy Shim", capability = DeviceCapability.DEVICE_SIGNATURE_TABLET)
+public class DummyShim implements DeviceInterface {
+
+	@Override
+	public void close() throws Exception {
+
+	}
+
+	@Override
+	public void configure(HashMap<String, Object> config) {
+
+	}
+
+	@Override
+	public void init() throws Exception {
+
+	}
+
+	@Override
+	public List<String> getConfigurationOptions() {
+		return null;
+	}
+
+	@Override
+	public boolean isProcessing() {
+		return false;
+	}
+
+	@Override
+	public boolean initJobRequest(JobStoreItem item) throws Exception {
+		return false;
+	}
+
+}
diff --git a/shim-library/src/main/java/org/freemedsoftware/device/types/AbnormalFlagCode.java b/shim-library/src/main/java/org/freemedsoftware/device/types/AbnormalFlagCode.java
new file mode 100644
index 0000000..6047023
--- /dev/null
+++ b/shim-library/src/main/java/org/freemedsoftware/device/types/AbnormalFlagCode.java
@@ -0,0 +1,46 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device.types;
+
+public enum AbnormalFlagCode {
+
+	BELOW_LOW_NORMAL("L"), ABOVE_HIGH_NORMAL("H"), BELOW_LOWER_PANIC_LIMIT("LL"), ABOVE_UPPER_PANIC_LIMIT(
+			"HH"), BELOW_INSTRUMENT_SCALE("<"), ABOVE_INSTRUMENT_SCALE(">"), NORMAL(
+			"N"), ABNORMAL("A"), VERY_ABNORMAL("AA"), NO_RANGE_DEFINED(null), SIGNIFICANT_CHANGE_UP(
+			"U"), SIGNIFICANT_CHANGE_DOWN("D"), BETTER("B"), WORSE("W"), SUCEPTIBLE(
+			"S"), RESISTANT("R"), INTERMEDIATE("I"), MODERATELY_SUCEPTIBLE("MS"), VERY_SUCEPTIBLE(
+			"VS");
+
+	private String txt = null;
+
+	private AbnormalFlagCode(String txt) {
+		this.txt = txt;
+	}
+
+	@Override
+	public String toString() {
+		return this.txt;
+	}
+}
diff --git a/shim-library/src/main/java/org/freemedsoftware/device/types/ObrRecord.java b/shim-library/src/main/java/org/freemedsoftware/device/types/ObrRecord.java
new file mode 100644
index 0000000..096878d
--- /dev/null
+++ b/shim-library/src/main/java/org/freemedsoftware/device/types/ObrRecord.java
@@ -0,0 +1,77 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device.types;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+public class ObrRecord implements Serializable {
+
+	private static final long serialVersionUID = 8699102427177717059L;
+
+	private List<ObxRecord> observations = new ArrayList<ObxRecord>();
+	private Date observationDate;
+	private Date observationDateEnd;
+	private SpecimenSourceCode specimenSource;
+
+	public void addObservation(ObxRecord observation) {
+		getObservations().add(observation);
+	}
+
+	public void setObservations(List<ObxRecord> observations) {
+		this.observations = observations;
+	}
+
+	public List<ObxRecord> getObservations() {
+		return observations;
+	}
+
+	public void setObservationDate(Date observationDate) {
+		this.observationDate = observationDate;
+	}
+
+	public Date getObservationDate() {
+		return observationDate;
+	}
+
+	public void setObservationDateEnd(Date observationDateEnd) {
+		this.observationDateEnd = observationDateEnd;
+	}
+
+	public Date getObservationDateEnd() {
+		return observationDateEnd;
+	}
+
+	public void setSpecimenSource(SpecimenSourceCode specimenSource) {
+		this.specimenSource = specimenSource;
+	}
+
+	public SpecimenSourceCode getSpecimenSource() {
+		return specimenSource;
+	}
+
+}
diff --git a/shim-library/src/main/java/org/freemedsoftware/device/types/ObxRecord.java b/shim-library/src/main/java/org/freemedsoftware/device/types/ObxRecord.java
new file mode 100644
index 0000000..2232197
--- /dev/null
+++ b/shim-library/src/main/java/org/freemedsoftware/device/types/ObxRecord.java
@@ -0,0 +1,88 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device.types;
+
+import java.io.Serializable;
+
+public class ObxRecord implements Serializable {
+
+	private static final long serialVersionUID = 773066854577636760L;
+
+	private String observationIdentifier;
+	private String observationValue;
+	private String units;
+	private String producerId;
+	private String observationMethod;
+	private AbnormalFlagCode abnormalFlag;
+
+	public void setObservationIdentifier(String observationIdentifier) {
+		this.observationIdentifier = observationIdentifier;
+	}
+
+	public String getObservationIdentifier() {
+		return observationIdentifier;
+	}
+
+	public void setObservationValue(String observationValue) {
+		this.observationValue = observationValue;
+	}
+
+	public String getObservationValue() {
+		return observationValue;
+	}
+
+	public void setUnits(String units) {
+		this.units = units;
+	}
+
+	public String getUnits() {
+		return units;
+	}
+
+	public void setProducerId(String producerId) {
+		this.producerId = producerId;
+	}
+
+	public String getProducerId() {
+		return producerId;
+	}
+
+	public void setObservationMethod(String observationMethod) {
+		this.observationMethod = observationMethod;
+	}
+
+	public String getObservationMethod() {
+		return observationMethod;
+	}
+
+	public void setAbnormalFlag(AbnormalFlagCode abnormalFlag) {
+		this.abnormalFlag = abnormalFlag;
+	}
+
+	public AbnormalFlagCode getAbnormalFlag() {
+		return abnormalFlag;
+	}
+
+}
diff --git a/shim-library/src/main/java/org/freemedsoftware/device/types/SpecimenSourceCode.java b/shim-library/src/main/java/org/freemedsoftware/device/types/SpecimenSourceCode.java
new file mode 100644
index 0000000..5c08082
--- /dev/null
+++ b/shim-library/src/main/java/org/freemedsoftware/device/types/SpecimenSourceCode.java
@@ -0,0 +1,65 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.device.types;
+
+public enum SpecimenSourceCode {
+
+	ABS("ABS"), AMN("AMN"), ASP("ASP"), BPH("BPH"), BIFL("BIFL"), BLDA("BLDA"), BBL(
+			"BBL"), BLDC("BLDC"), BPU("BPU"), BLDV("BLDV"), BON("BON"), BRTH(
+			"BRTH"), BRO("BRO"), BRN("BRN"), CALC("CALC"), CDM("CDM"), CNL(
+			"CNL"), CTP("CTP"), CSF("CSF"), CVM("CVM"), CVX("CVX"), COL("COL"), CLBD(
+			"CLBD"), CNJT("CNJT"), CUR("CUR"), CYST("CYST"), DIAF("DIAF"), DOSE(
+			"DOSE"), DRN("DRN"), DUFL("DUFL"), EAR("EAR"), EARW("EARW"), ELT(
+			"ELT"), ENDC("ENDC"), ENDM("ENDM"), EOS("EOS"), RBC("RBC"), EYE(
+			"EYE"), EXHLD("EXHLD"), FIB("FIB"), FLT("FLT"), FIST("FIST"), FLU(
+			"FLU"), GAS("GAS"), GAST("GAST"), GEN("GEN"), GENC("GENC"), GENL(
+			"GENL"), GENV("GENV"), HAR("HAR"), IHG("IHG"), IT("IT"), ISLT(
+			"ISLT"), LAM("LAM"), WBC("WBC"), LN("LN"), LNA("LNA"), LNV("LNV"), LIQ(
+			"LIQ"), LYM("LYM"), MAC("MAC"), MAR("MAR"), MEC("MEC"), MBLD("MBLD"), MLK(
+			"MLK"), MILK("MILK"), NAIL("NAIL"), NOS("NOS"), ORH("ORH"), PAFL(
+			"PAFL"), PAT("PAT"), PRT("PRT"), PLC("PLC"), PLAS("PLAS"), PLB(
+			"PLB"), PLR("PLR"), PMN("PMN"), PPP("PPP"), PRP("PRP"), PUS("PUS"), RT(
+			"RT"), SAL("SAL"), SEM("SEM"), SER("SER"), SKN("SKN"), SKM("SKM"), SPRM(
+			"SPRM"), SPT("SPT"), SPTC("SPTC"), SPTT("SPTT"), STON("STON"), STL(
+			"STL"), SWT("SWT"), SNV("SNV"), TEAR("TEAR"), THRT("THRT"), THRB(
+			"THRB"), TISS("TISS"), TISG("TISG"), TLGI("TLGI"), TLNG("TLNG"), TISPL(
+			"TISPL"), TSMI("TSMI"), TISU("TISU"), TUB("TUB"), ULC("ULC"), UMB(
+			"UMB"), UMED("UMED"), URTH("URTH"), UR("UR"), URC("URC"), URT("URT"), URNS(
+			"URNS"), USUB("USUB"), VOM("VOM"), BLD("BLD"), BDY("BDY"), WAT(
+			"WAT"), WICK("WICK"), WND("WND"), WNDA("WNDA"), WNDE("WNDE"), WNDD(
+			"WNDD"), XXX("XXX");
+
+	private String txt = null;
+
+	SpecimenSourceCode(String txt) {
+		this.txt = txt;
+	}
+
+	@Override
+	public String toString() {
+		return this.txt;
+	}
+
+}
diff --git a/shim-library/src/test/java/org/freemedsoftware/device/ShimDeviceManagerTest.java b/shim-library/src/test/java/org/freemedsoftware/device/ShimDeviceManagerTest.java
new file mode 100644
index 0000000..4dc6934
--- /dev/null
+++ b/shim-library/src/test/java/org/freemedsoftware/device/ShimDeviceManagerTest.java
@@ -0,0 +1,41 @@
+package org.freemedsoftware.device;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ */
+public class ShimDeviceManagerTest extends TestCase {
+	/**
+	 * Create the test case
+	 * 
+	 * @param testName
+	 *            name of the test case
+	 */
+	public ShimDeviceManagerTest(String testName) {
+		super(testName);
+	}
+
+	/**
+	 * @return the suite of tests being tested
+	 */
+	public static Test suite() {
+		return new TestSuite(ShimDeviceManagerTest.class);
+	}
+
+	public void testScanDeviceDrivers() {
+		try {
+			ShimDeviceManager<DeviceInterface> i = new ShimDeviceManager<DeviceInterface>();
+			i.scanShimDevices();
+			assertTrue(true);
+		} catch (InstantiationException e) {
+			e.printStackTrace();
+		} catch (IllegalAccessException e) {
+			e.printStackTrace();
+		} catch (ClassNotFoundException e) {
+			e.printStackTrace();
+		}
+	}
+}
diff --git a/shim-webapp/.classpath b/shim-webapp/.classpath
new file mode 100644
index 0000000..7e0cbcb
--- /dev/null
+++ b/shim-webapp/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/>
+	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/shim-webapp/.project b/shim-webapp/.project
new file mode 100644
index 0000000..5ae9fbe
--- /dev/null
+++ b/shim-webapp/.project
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>shim-webapp</name>
+	<comment>NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse.</comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
+	</natures>
+</projectDescription>
diff --git a/shim-webapp/.settings/.jsdtscope b/shim-webapp/.settings/.jsdtscope
new file mode 100644
index 0000000..bbb8e68
--- /dev/null
+++ b/shim-webapp/.settings/.jsdtscope
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject">
+		<attributes>
+			<attribute name="hide" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
+	<classpathentry kind="output" path=""/>
+</classpath>
diff --git a/shim-webapp/.settings/org.eclipse.jdt.core.prefs b/shim-webapp/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..b51cf30
--- /dev/null
+++ b/shim-webapp/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+#Thu Aug 12 19:41:01 EDT 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/shim-webapp/.settings/org.eclipse.wst.common.component b/shim-webapp/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..0a2e254
--- /dev/null
+++ b/shim-webapp/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="shim-webapp">
+        <wb-resource deploy-path="/" source-path="/src/main/webapp"/>
+        <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
+        <dependent-module deploy-path="/WEB-INF/lib" handle="module:/resource/shim-library/shim-library">
+            <dependency-type>uses</dependency-type>
+        </dependent-module>
+        <dependent-module deploy-path="/WEB-INF/lib" handle="module:/resource/shim-driver-label-escpos/shim-driver-label-escpos">
+            <dependency-type>uses</dependency-type>
+        </dependent-module>
+        <dependent-module deploy-path="/WEB-INF/lib" handle="module:/resource/shim-driver-signature.topaz/shim-driver-signature-topaz">
+            <dependency-type>uses</dependency-type>
+        </dependent-module>
+        <dependent-module deploy-path="/WEB-INF/lib" handle="module:/resource/shim-driver-signature-dummy/shim-driver-signature-dummy">
+            <dependency-type>uses</dependency-type>
+        </dependent-module>
+        <property name="context-root" value="shim-webapp"/>
+        <property name="java-output-path" value="/shim-webapp/target/classes"/>
+    </wb-module>
+</project-modules>
diff --git a/shim-webapp/.settings/org.eclipse.wst.common.project.facet.core.xml b/shim-webapp/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..d5b0a29
--- /dev/null
+++ b/shim-webapp/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <installed facet="jst.java" version="1.4"/>
+  <installed facet="jst.web" version="2.3"/>
+</faceted-project>
diff --git a/shim-webapp/.settings/org.eclipse.wst.jsdt.ui.superType.container b/shim-webapp/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/shim-webapp/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/shim-webapp/.settings/org.eclipse.wst.jsdt.ui.superType.name b/shim-webapp/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/shim-webapp/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/shim-webapp/.settings/org.maven.ide.eclipse.prefs b/shim-webapp/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..dd6265b
--- /dev/null
+++ b/shim-webapp/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Wed Aug 04 13:07:27 EDT 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/shim-webapp/README b/shim-webapp/README
new file mode 100644
index 0000000..2c379c2
--- /dev/null
+++ b/shim-webapp/README
@@ -0,0 +1,98 @@
+$Id$
+
+Basics:
+
+SHIM webapp component. This is a J2EE web application with CXF-based
+SOAP/REST services. The WSDL is available at
+
+	http://host:port/shim/services/ShimService?wsdl
+
+(with the appropriate values of "host" and "port" used, of course. It
+uses an internal job store queueing system which is by default stored in
+${catalina.home}/work/jobstore.db but can be overridden by the properties
+"overrides" file, which can be specified by defining the "properties"
+property like this:
+
+	-Dshim.properties=/path/to/the/config/shim.properties
+
+Building:
+
+1) "mvn package". You'll probably have to run this from the root of the
+   shim source so that all dependent libraries are built, etc. The final
+   packaged version is available in ${SHIM}/shim-webapp/target/shim.war
+
+Testing:
+
+1) "mvn jetty:run" will launch an embedded Jetty instance on the default
+   port (8080), so the interface can be reached at
+
+   http://localhost:8080/shim-webapp/
+
+Installation:
+
+1) Copy "shim.war" from "target" into webapps directory of Tomcat
+   install.
+
+2) Copy native libraries into the appropriate place.
+
+3) Create shim.properties file with any overrides for configuration.
+   Anything which isn't overridden has default values which should
+   work for most common configurations. *Most*.
+
+4) Start tomcat with:
+
+   JAVA_OPTS="-Dshim.properties=${TOMCAT_HOME}/shim.properties" ./bin/catalina.sh start
+
+--- Installation with Debian packages/integration ---
+
+1) Tomcat 5.5: apt-get install tomcat5.5 sun-java6-jre
+   Tomcat 6.x: apt-get install tomcat6 sun-java6-jre
+
+2) Copy librxtx*.so into /usr/lib/jvm/java-6-sun/jre/lib/$ARCH/
+   (where $ARCH is amd64, i386, etc). You have to use rxtx v2.2pre2,
+   otherwise it won't work. Don't ask why, just understand it won't
+   work if you don't use the newer version. Don't use the
+   librxtx-java package, it's old.
+
+3) Copy shim.war from "target" into
+   /var/lib/tomcat5.5/webapps/ and make its owner "tomcat55" or
+   "tomcat" depending on the version.
+
+4) Append the following lines to /etc/default/tomcat5.5 or
+   /etc/default/tomcat depending on the version:
+
+   JAVA_HOME=/usr/lib/jvm/java-6-sun
+   JAVA_OPTS=" -Dshim.properties=/etc/shim.properties "
+   TOMCAT5_SECURITY=no
+
+   if there is already a JAVA_OPTS clause, add the -D... phrase to it.
+
+5) Add credentials to /var/lib/tomcat5.5/conf/tomcat-users.xml or
+   /var/lib/tomcat/conf/tomcat-users.xml like:
+
+   <role rolename="default" />
+   <user username="Administrator" password="password" roles="default" />
+
+6) Create shim.properties file with any overrides.
+   (Anything which isn't overridden has default values.)
+
+   Make sure to copy the file to /etc/shim.properties when you
+   have finished making your changes.
+
+7) Add the "tomcat55" or "tomcat" user (depending on the version) to
+   the "lp" and "dialout" groups, and make any necessary udev changes
+   for Topaz signature pads, etc.
+
+8) Start tomcat with:
+
+   Tomcat 5.5: /etc/init.d/tomcat5.5 restart
+   Tomcat 6:   /etc/init.d/tomcat restart
+
+9) The URL for this instance will be:
+
+   Tomcat 5.5:
+   http://${MACHINE-NAME-OR-IP}:8180/shim/services/ShimService?wsdl
+
+   Tomcat 6:
+   http://${MACHINE-NAME-OR-IP}:8080/shim/services/ShimService?wsdl
+
diff --git a/shim-webapp/jetty-realm.properties b/shim-webapp/jetty-realm.properties
new file mode 100644
index 0000000..ed51438
--- /dev/null
+++ b/shim-webapp/jetty-realm.properties
@@ -0,0 +1 @@
+Administrator: password,default
diff --git a/shim-webapp/packaging/win32/INSTALLLICENSE b/shim-webapp/packaging/win32/INSTALLLICENSE
new file mode 100644
index 0000000..ef2de36
--- /dev/null
+++ b/shim-webapp/packaging/win32/INSTALLLICENSE
@@ -0,0 +1,991 @@
+-------------------- FreeSHIM License ----------------------
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+

+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+

+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+

+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+

+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+------------------ TOMCAT LICENSE -------------------
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+
+APACHE TOMCAT SUBCOMPONENTS: 
+
+Apache Tomcat includes a number of subcomponents with separate copyright notices
+and license terms. Your use of these subcomponents is subject to the terms and
+conditions of the following licenses. 
+
+
+For the jasper-jdt.jar component:
+
+Eclipse Public License - v 1.0
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
+CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+a) in the case of the initial Contributor, the initial code and documentation
+distributed under this Agreement, and
+
+b) in the case of each subsequent Contributor:
+
+i) changes to the Program, and
+
+ii) additions to the Program;
+
+where such changes and/or additions to the Program originate from and are
+distributed by that particular Contributor. A Contribution 'originates' from a
+Contributor if it was added to the Program by such Contributor itself or anyone
+acting on such Contributor's behalf. Contributions do not include additions to
+the Program which: (i) are separate modules of software distributed in
+conjunction with the Program under their own license agreement, and (ii) are not
+derivative works of the Program.
+
+"Contributor" means any person or entity that distributes the Program.
+
+"Licensed Patents" mean patent claims licensable by a Contributor which are
+necessarily infringed by the use or sale of its Contribution alone or when
+combined with the Program.
+
+"Program" means the Contributions distributed in accordance with this Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement,
+including all Contributors.
+
+2. GRANT OF RIGHTS
+
+a) Subject to the terms of this Agreement, each Contributor hereby grants
+Recipient a non-exclusive, worldwide, royalty-free copyright license to
+reproduce, prepare derivative works of, publicly display, publicly perform,
+distribute and sublicense the Contribution of such Contributor, if any, and such
+derivative works, in source code and object code form.
+
+b) Subject to the terms of this Agreement, each Contributor hereby grants
+Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed
+Patents to make, use, sell, offer to sell, import and otherwise transfer the
+Contribution of such Contributor, if any, in source code and object code form.
+This patent license shall apply to the combination of the Contribution and the
+Program if, at the time the Contribution is added by the Contributor, such
+addition of the Contribution causes such combination to be covered by the
+Licensed Patents. The patent license shall not apply to any other combinations
+which include the Contribution. No hardware per se is licensed hereunder.
+
+c) Recipient understands that although each Contributor grants the licenses to
+its Contributions set forth herein, no assurances are provided by any
+Contributor that the Program does not infringe the patent or other intellectual
+property rights of any other entity. Each Contributor disclaims any liability to
+Recipient for claims brought by any other entity based on infringement of
+intellectual property rights or otherwise. As a condition to exercising the
+rights and licenses granted hereunder, each Recipient hereby assumes sole
+responsibility to secure any other intellectual property rights needed, if any.
+For example, if a third party patent license is required to allow Recipient to
+distribute the Program, it is Recipient's responsibility to acquire that license
+before distributing the Program.
+
+d) Each Contributor represents that to its knowledge it has sufficient copyright
+rights in its Contribution, if any, to grant the copyright license set forth in
+this Agreement.
+
+3. REQUIREMENTS
+
+A Contributor may choose to distribute the Program in object code form under its
+own license agreement, provided that:
+
+a) it complies with the terms and conditions of this Agreement; and
+
+b) its license agreement:
+
+i) effectively disclaims on behalf of all Contributors all warranties and
+conditions, express and implied, including warranties or conditions of title and
+non-infringement, and implied warranties or conditions of merchantability and
+fitness for a particular purpose;
+
+ii) effectively excludes on behalf of all Contributors all liability for
+damages, including direct, indirect, special, incidental and consequential
+damages, such as lost profits;
+
+iii) states that any provisions which differ from this Agreement are offered by
+that Contributor alone and not by any other party; and
+
+iv) states that source code for the Program is available from such Contributor,
+and informs licensees how to obtain it in a reasonable manner on or through a
+medium customarily used for software exchange.
+
+When the Program is made available in source code form:
+
+a) it must be made available under this Agreement; and
+
+b) a copy of this Agreement must be included with each copy of the Program.
+
+Contributors may not remove or alter any copyright notices contained within the
+Program.
+
+Each Contributor must identify itself as the originator of its Contribution, if
+any, in a manner that reasonably allows subsequent Recipients to identify the
+originator of the Contribution.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities with
+respect to end users, business partners and the like. While this license is
+intended to facilitate the commercial use of the Program, the Contributor who
+includes the Program in a commercial product offering should do so in a manner
+which does not create potential liability for other Contributors. Therefore, if
+a Contributor includes the Program in a commercial product offering, such
+Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
+every other Contributor ("Indemnified Contributor") against any losses, damages
+and costs (collectively "Losses") arising from claims, lawsuits and other legal
+actions brought by a third party against the Indemnified Contributor to the
+extent caused by the acts or omissions of such Commercial Contributor in
+connection with its distribution of the Program in a commercial product
+offering. The obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In order
+to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
+Contributor in writing of such claim, and b) allow the Commercial Contributor
+to control, and cooperate with the Commercial Contributor in, the defense and
+any related settlement negotiations. The Indemnified Contributor may
+participate in any such claim at its own expense.
+
+For example, a Contributor might include the Program in a commercial product
+offering, Product X. That Contributor is then a Commercial Contributor. If that
+Commercial Contributor then makes performance claims, or offers warranties
+related to Product X, those performance claims and warranties are such
+Commercial Contributor's responsibility alone. Under this section, the
+Commercial Contributor would have to defend claims against the other
+Contributors related to those performance claims and warranties, and if a court
+requires any other Contributor to pay any damages as a result, the Commercial
+Contributor must pay those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
+IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
+Recipient is solely responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its exercise of
+rights under this Agreement , including but not limited to the risks and costs
+of program errors, compliance with applicable laws, damage to or loss of data,
+programs or equipment, and unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
+CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
+PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
+GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under applicable
+law, it shall not affect the validity or enforceability of the remainder of the
+terms of this Agreement, and without further action by the parties hereto, such
+provision shall be reformed to the minimum extent necessary to make such
+provision valid and enforceable.
+
+If Recipient institutes patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Program itself
+(excluding combinations of the Program with other software or hardware)
+infringes such Recipient's patent(s), then such Recipient's rights granted under
+Section 2(b) shall terminate as of the date such litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it fails to
+comply with any of the material terms or conditions of this Agreement and does
+not cure such failure in a reasonable period of time after becoming aware of
+such noncompliance. If all Recipient's rights under this Agreement terminate,
+Recipient agrees to cease use and distribution of the Program as soon as
+reasonably practicable. However, Recipient's obligations under this Agreement
+and any licenses granted by Recipient relating to the Program shall continue and
+survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement, but in
+order to avoid inconsistency the Agreement is copyrighted and may only be
+modified in the following manner. The Agreement Steward reserves the right to
+publish new versions (including revisions) of this Agreement from time to time.
+No one other than the Agreement Steward has the right to modify this Agreement.
+The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation
+may assign the responsibility to serve as the Agreement Steward to a suitable
+separate entity. Each new version of the Agreement will be given a
+distinguishing version number. The Program (including Contributions) may always
+be distributed subject to the version of the Agreement under which it was
+received. In addition, after a new version of the Agreement is published,
+Contributor may elect to distribute the Program (including its Contributions)
+under the new version. Except as expressly stated in Sections 2(a) and 2(b)
+above, Recipient receives no rights or licenses to the intellectual property of
+any Contributor under this Agreement, whether expressly, by implication,
+estoppel or otherwise. All rights in the Program not expressly granted under
+this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and the
+intellectual property laws of the United States of America. No party to this
+Agreement will bring a legal action under this Agreement more than one year
+after the cause of action arose. Each party waives its rights to a jury trial in
+any resulting litigation.
+
+
+For the Windows Installer component:
+
+    * All NSIS source code, plug-ins, documentation, examples, header files and
+       graphics, with the exception of the compression modules and where
+       otherwise noted, are licensed under the zlib/libpng license.
+    * The zlib compression module for NSIS is licensed under the zlib/libpng
+       license.
+    * The bzip2 compression module for NSIS is licensed under the bzip2 license.
+    * The lzma compression module for NSIS is licensed under the Common Public
+       License version 1.0. 
+
+zlib/libpng license
+
+This software is provided 'as-is', without any express or implied warranty. In
+no event will the authors be held liable for any damages arising from the use of
+this software.
+
+Permission is granted to anyone to use this software for any purpose, including
+commercial applications, and to alter it and redistribute it freely, subject to
+the following restrictions:
+
+   1. The origin of this software must not be misrepresented; you must not claim
+       that you wrote the original software. If you use this software in a
+       product, an acknowledgment in the product documentation would be
+       appreciated but is not required.
+   2. Altered source versions must be plainly marked as such, and must not be
+       misrepresented as being the original software.
+   3. This notice may not be removed or altered from any source distribution. 
+
+bzip2 license
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+       this list of conditions and the following disclaimer.
+   2. The origin of this software must not be misrepresented; you must not claim
+       that you wrote the original software. If you use this software in a
+       product, an acknowledgment in the product documentation would be
+       appreciated but is not required.
+   3. Altered source versions must be plainly marked as such, and must not be
+       misrepresented as being the original software.
+   4. The name of the author may not be used to endorse or promote products
+       derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+OF SUCH DAMAGE.
+
+Julian Seward, Cambridge, UK.
+
+jseward at acm.org
+Common Public License version 1.0
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC
+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
+CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+a) in the case of the initial Contributor, the initial code and documentation
+distributed under this Agreement, and b) in the case of each subsequent
+Contributor:
+
+i) changes to the Program, and
+
+ii) additions to the Program;
+
+where such changes and/or additions to the Program originate from and are
+distributed by that particular Contributor. A Contribution 'originates' from a
+Contributor if it was added to the Program by such Contributor itself or anyone
+acting on such Contributor's behalf. Contributions do not include additions to
+the Program which: (i) are separate modules of software distributed in
+conjunction with the Program under their own license agreement, and (ii) are not
+derivative works of the Program.
+
+"Contributor" means any person or entity that distributes the Program.
+
+"Licensed Patents " mean patent claims licensable by a Contributor which are
+necessarily infringed by the use or sale of its Contribution alone or when
+combined with the Program.
+
+"Program" means the Contributions distributed in accordance with this Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement,
+including all Contributors.
+
+2. GRANT OF RIGHTS
+
+a) Subject to the terms of this Agreement, each Contributor hereby grants
+Recipient a non-exclusive, worldwide, royalty-free copyright license to
+reproduce, prepare derivative works of, publicly display, publicly perform,
+distribute and sublicense the Contribution of such Contributor, if any, and such
+derivative works, in source code and object code form.
+
+b) Subject to the terms of this Agreement, each Contributor hereby grants
+Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed
+Patents to make, use, sell, offer to sell, import and otherwise transfer the
+Contribution of such Contributor, if any, in source code and object code form.
+This patent license shall apply to the combination of the Contribution and the
+Program if, at the time the Contribution is added by the Contributor, such
+addition of the Contribution causes such combination to be covered by the
+Licensed Patents. The patent license shall not apply to any other combinations
+which include the Contribution. No hardware per se is licensed hereunder.
+
+c) Recipient understands that although each Contributor grants the licenses to
+its Contributions set forth herein, no assurances are provided by any
+Contributor that the Program does not infringe the patent or other intellectual
+property rights of any other entity. Each Contributor disclaims any liability to
+Recipient for claims brought by any other entity based on infringement of
+intellectual property rights or otherwise. As a condition to exercising the
+rights and licenses granted hereunder, each Recipient hereby assumes sole
+responsibility to secure any other intellectual property rights needed, if any.
+For example, if a third party patent license is required to allow Recipient to
+distribute the Program, it is Recipient's responsibility to acquire that license
+before distributing the Program.
+
+d) Each Contributor represents that to its knowledge it has sufficient copyright
+rights in its Contribution, if any, to grant the copyright license set forth in
+this Agreement.
+
+3. REQUIREMENTS
+
+A Contributor may choose to distribute the Program in object code form under its
+own license agreement, provided that:
+
+a) it complies with the terms and conditions of this Agreement; and
+
+b) its license agreement:
+
+i) effectively disclaims on behalf of all Contributors all warranties and
+conditions, express and implied, including warranties or conditions of title and
+non-infringement, and implied warranties or conditions of merchantability and
+fitness for a particular purpose;
+
+ii) effectively excludes on behalf of all Contributors all liability for
+damages, including direct, indirect, special, incidental and consequential
+damages, such as lost profits;
+
+iii) states that any provisions which differ from this Agreement are offered by
+that Contributor alone and not by any other party; and
+
+iv) states that source code for the Program is available from such Contributor,
+and informs licensees how to obtain it in a reasonable manner on or through a
+medium customarily used for software exchange.
+
+When the Program is made available in source code form:
+
+a) it must be made available under this Agreement; and
+
+b) a copy of this Agreement must be included with each copy of the Program.
+
+Contributors may not remove or alter any copyright notices contained within the
+Program.
+
+Each Contributor must identify itself as the originator of its Contribution, if
+any, in a manner that reasonably allows subsequent Recipients to identify the
+originator of the Contribution.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities with
+respect to end users, business partners and the like. While this license is
+intended to facilitate the commercial use of the Program, the Contributor who
+includes the Program in a commercial product offering should do so in a manner
+which does not create potential liability for other Contributors. Therefore, if
+a Contributor includes the Program in a commercial product offering, such
+Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
+every other Contributor ("Indemnified Contributor") against any losses, damages
+and costs (collectively "Losses") arising from claims, lawsuits and other legal
+actions brought by a third party against the Indemnified Contributor to the
+extent caused by the acts or omissions of such Commercial Contributor in
+connection with its distribution of the Program in a commercial product
+offering. The obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In order
+to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
+Contributor in writing of such claim, and b) allow the Commercial Contributor to
+control, and cooperate with the Commercial Contributor in, the defense and any
+related settlement negotiations. The Indemnified Contributor may participate in
+any such claim at its own expense.
+
+For example, a Contributor might include the Program in a commercial product
+offering, Product X. That Contributor is then a Commercial Contributor. If that
+Commercial Contributor then makes performance claims, or offers warranties
+related to Product X, those performance claims and warranties are such
+Commercial Contributor's responsibility alone. Under this section, the
+Commercial Contributor would have to defend claims against the other
+Contributors related to those performance claims and warranties, and if a court
+requires any other Contributor to pay any damages as a result, the Commercial
+Contributor must pay those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
+IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
+Recipient is solely responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its exercise of
+rights under this Agreement, including but not limited to the risks and costs of
+program errors, compliance with applicable laws, damage to or loss of data,
+programs or equipment, and unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
+CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
+PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
+GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under applicable
+law, it shall not affect the validity or enforceability of the remainder of the
+terms of this Agreement, and without further action by the parties hereto, such
+provision shall be reformed to the minimum extent necessary to make such
+provision valid and enforceable.
+
+If Recipient institutes patent litigation against a Contributor with respect to
+a patent applicable to software (including a cross-claim or counterclaim in a
+lawsuit), then any patent licenses granted by that Contributor to such Recipient
+under this Agreement shall terminate as of the date such litigation is filed. In
+addition, if Recipient institutes patent litigation against any entity
+(including a cross-claim or counterclaim in a lawsuit) alleging that the Program
+itself (excluding combinations of the Program with other software or hardware)
+infringes such Recipient's patent(s), then such Recipient's rights granted under
+Section 2(b) shall terminate as of the date such litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it fails to
+comply with any of the material terms or conditions of this Agreement and does
+not cure such failure in a reasonable period of time after becoming aware of
+such noncompliance. If all Recipient's rights under this Agreement terminate,
+Recipient agrees to cease use and distribution of the Program as soon as
+reasonably practicable. However, Recipient's obligations under this Agreement
+and any licenses granted by Recipient relating to the Program shall continue and
+survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement, but in
+order to avoid inconsistency the Agreement is copyrighted and may only be
+modified in the following manner. The Agreement Steward reserves the right to
+publish new versions (including revisions) of this Agreement from time to time.
+No one other than the Agreement Steward has the right to modify this Agreement.
+IBM is the initial Agreement Steward. IBM may assign the responsibility to serve
+as the Agreement Steward to a suitable separate entity. Each new version of the
+Agreement will be given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the Agreement
+under which it was received. In addition, after a new version of the Agreement
+is published, Contributor may elect to distribute the Program (including its
+Contributions) under the new version. Except as expressly stated in Sections
+2(a) and 2(b) above, Recipient receives no rights or licenses to the
+intellectual property of any Contributor under this Agreement, whether
+expressly, by implication, estoppel or otherwise. All rights in the Program not
+expressly granted under this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and the
+intellectual property laws of the United States of America. No party to this
+Agreement will bring a legal action under this Agreement more than one year
+after the cause of action arose. Each party waives its rights to a jury trial in
+any resulting litigation.
+
+Special exception for LZMA compression module
+
+Igor Pavlov and Amir Szekely, the authors of the LZMA compression module for
+NSIS, expressly permit you to statically or dynamically link your code (or bind
+by name) to the files from the LZMA compression module for NSIS without
+subjecting your linked code to the terms of the Common Public license version
+1.0. Any modifications or additions to files from the LZMA compression module
+for NSIS, however, are subject to the terms of the Common Public License version
+1.0. 
diff --git a/shim-webapp/packaging/win32/build.sh b/shim-webapp/packaging/win32/build.sh
new file mode 100755
index 0000000..8d30cbe
--- /dev/null
+++ b/shim-webapp/packaging/win32/build.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+TOMCAT_VERSION=6.0.32
+P="$( cd "$(dirname "$0")"; pwd )"
+
+cd "$P"
+
+if [ ! -f ../../target/shim.war ] ; then
+	echo "Create shim.war"
+	( cd ../.. ; mvn package || exit 1 )
+fi
+
+if [ ! -f apache-tomcat-${TOMCAT_VERSION}-windows-x86.zip ] ; then
+	echo "Grabbing tomcat ${TOMCAT_VERSION} binary package"
+	wget -c http://apache.ziply.com/tomcat/tomcat-6/v${TOMCAT_VERSION}/bin/apache-tomcat-${TOMCAT_VERSION}-windows-x86.zip
+fi
+
+if [ ! -d apache-tomcat-${TOMCAT_VERSION} ]; then
+	echo "Decompression tomcat archive"
+	unzip apache-tomcat-${TOMCAT_VERSION}-windows-x86.zip
+fi
+
+echo "Building package"
+makensis shim.nsi
+
diff --git a/shim-webapp/packaging/win32/config.ini b/shim-webapp/packaging/win32/config.ini
new file mode 100644
index 0000000..b484513
--- /dev/null
+++ b/shim-webapp/packaging/win32/config.ini
@@ -0,0 +1,58 @@
+[Settings]
+NumFields=7
+
+[Field 1]
+Type=Label
+Text=HTTP/1.1 Connector Port
+left=0
+right=150
+top=5
+bottom=20
+
+[Field 2]
+Type=Text
+State=8180
+MaxLen=5
+left=150
+right=200
+top=5
+bottom=18
+
+[Field 3]
+Type=Label
+text=Tomcat Administrator Login (optional)
+left=0
+right=300
+top=30
+bottom=45
+
+[Field 4]
+Type=Label
+Text=User Name
+left=10
+right=150
+top=50
+bottom=65
+
+[Field 5]
+Type=Text
+left=150
+right=250
+top=50
+bottom=63
+
+[Field 6]
+Type=Label
+Text=Password
+left=10
+right=150
+top=70
+bottom=85
+
+[Field 7]
+Type=Password
+left=150
+right=250
+top=70
+bottom=83
+
diff --git a/shim-webapp/packaging/win32/confinstall/server_1.xml b/shim-webapp/packaging/win32/confinstall/server_1.xml
new file mode 100644
index 0000000..3661018
--- /dev/null
+++ b/shim-webapp/packaging/win32/confinstall/server_1.xml
@@ -0,0 +1,69 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!-- Note:  A "Server" is not itself a "Container", so you may not
+     define subcomponents such as "Valves" at this level.
+     Documentation at /docs/config/server.html
+ -->
+<Server port="8005" shutdown="SHUTDOWN">
+
+  <!--APR library loader. Documentation at /docs/apr.html -->
+  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
+  <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
+  <Listener className="org.apache.catalina.core.JasperListener" />
+  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
+  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
+  <!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html -->
+  <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
+  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
+
+  <!-- Global JNDI resources
+       Documentation at /docs/jndi-resources-howto.html
+  -->
+  <GlobalNamingResources>
+    <!-- Editable user database that can also be used by
+         UserDatabaseRealm to authenticate users
+    -->
+    <Resource name="UserDatabase" auth="Container"
+              type="org.apache.catalina.UserDatabase"
+              description="User database that can be updated and saved"
+              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
+              pathname="conf/tomcat-users.xml" />
+  </GlobalNamingResources>
+
+  <!-- A "Service" is a collection of one or more "Connectors" that share
+       a single "Container" Note:  A "Service" is not itself a "Container", 
+       so you may not define subcomponents such as "Valves" at this level.
+       Documentation at /docs/config/service.html
+   -->
+  <Service name="Catalina">
+  
+    <!--The connectors can use a shared executor, you can define one or more named thread pools-->
+    <!--
+    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" 
+        maxThreads="150" minSpareThreads="4"/>
+    -->
+    
+    
+    <!-- A "Connector" represents an endpoint by which requests are received
+         and responses are returned. Documentation at :
+         Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
+         Java AJP  Connector: /docs/config/ajp.html
+         APR (HTTP/AJP) Connector: /docs/apr.html
+         Define a non-SSL HTTP/1.1 Connector on port 8080
+    -->
+    <Connector 
\ No newline at end of file
diff --git a/shim-webapp/packaging/win32/confinstall/server_2.xml b/shim-webapp/packaging/win32/confinstall/server_2.xml
new file mode 100644
index 0000000..e070cea
--- /dev/null
+++ b/shim-webapp/packaging/win32/confinstall/server_2.xml
@@ -0,0 +1,80 @@
+ protocol="HTTP/1.1" 
+               connectionTimeout="20000" 
+               redirectPort="8443" />
+    <!-- A "Connector" using the shared thread pool-->
+    <!--
+    <Connector executor="tomcatThreadPool"
+               port="8080" protocol="HTTP/1.1" 
+               connectionTimeout="20000" 
+               redirectPort="8443" />
+    -->           
+    <!-- Define a SSL HTTP/1.1 Connector on port 8443
+         This connector uses the JSSE configuration, when using APR, the 
+         connector should be using the OpenSSL style configuration
+         described in the APR documentation -->
+    <!--
+    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
+               maxThreads="150" scheme="https" secure="true"
+               clientAuth="false" sslProtocol="TLS" />
+    -->
+
+    <!-- Define an AJP 1.3 Connector on port 8009 -->
+    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
+
+
+    <!-- An Engine represents the entry point (within Catalina) that processes
+         every request.  The Engine implementation for Tomcat stand alone
+         analyzes the HTTP headers included with the request, and passes them
+         on to the appropriate Host (virtual host).
+         Documentation at /docs/config/engine.html -->
+
+    <!-- You should set jvmRoute to support load-balancing via AJP ie :
+    <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">         
+    --> 
+    <Engine name="Catalina" defaultHost="localhost">
+
+      <!--For clustering, please take a look at documentation at:
+          /docs/cluster-howto.html  (simple how to)
+          /docs/config/cluster.html (reference documentation) -->
+      <!--
+      <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
+      -->        
+
+      <!-- The request dumper valve dumps useful debugging information about
+           the request and response data received and sent by Tomcat.
+           Documentation at: /docs/config/valve.html -->
+      <!--
+      <Valve className="org.apache.catalina.valves.RequestDumperValve"/>
+      -->
+
+      <!-- This Realm uses the UserDatabase configured in the global JNDI
+           resources under the key "UserDatabase".  Any edits
+           that are performed against this UserDatabase are immediately
+           available for use by the Realm.  -->
+      <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
+             resourceName="UserDatabase"/>
+
+      <!-- Define the default virtual host
+           Note: XML Schema validation will not work with Xerces 2.2.
+       -->
+      <Host name="localhost"  appBase="webapps"
+            unpackWARs="true" autoDeploy="true"
+            xmlValidation="false" xmlNamespaceAware="false">
+
+        <!-- SingleSignOn valve, share authentication between web applications
+             Documentation at: /docs/config/valve.html -->
+        <!--
+        <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
+        -->
+
+        <!-- Access log processes all example.
+             Documentation at: /docs/config/valve.html -->
+        <!--
+        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"  
+               prefix="localhost_access_log." suffix=".txt" pattern="common" resolveHosts="false"/>
+        -->
+
+      </Host>
+    </Engine>
+  </Service>
+</Server>
diff --git a/shim-webapp/packaging/win32/confinstall/tomcat-users_1.xml b/shim-webapp/packaging/win32/confinstall/tomcat-users_1.xml
new file mode 100644
index 0000000..cde187d
--- /dev/null
+++ b/shim-webapp/packaging/win32/confinstall/tomcat-users_1.xml
@@ -0,0 +1,17 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<tomcat-users>
diff --git a/shim-webapp/packaging/win32/confinstall/tomcat-users_2.xml b/shim-webapp/packaging/win32/confinstall/tomcat-users_2.xml
new file mode 100644
index 0000000..452c172
--- /dev/null
+++ b/shim-webapp/packaging/win32/confinstall/tomcat-users_2.xml
@@ -0,0 +1,13 @@
+<!--
+  NOTE:  The sample user and role entries below are wrapped in a comment
+  and thus are ignored when reading this file. Do not forget to remove
+  <!.. ..> that surrounds them.
+-->
+<!--
+  <role rolename="tomcat"/>
+  <role rolename="role1"/>
+  <user username="tomcat" password="tomcat" roles="tomcat"/>
+  <user username="both" password="tomcat" roles="tomcat,role1"/>
+  <user username="role1" password="tomcat" roles="role1"/>
+-->
+</tomcat-users>
diff --git a/shim-webapp/packaging/win32/header.bmp b/shim-webapp/packaging/win32/header.bmp
new file mode 100644
index 0000000..b19e056
Binary files /dev/null and b/shim-webapp/packaging/win32/header.bmp differ
diff --git a/shim-webapp/packaging/win32/jvm.ini b/shim-webapp/packaging/win32/jvm.ini
new file mode 100644
index 0000000..1ffeeb1
--- /dev/null
+++ b/shim-webapp/packaging/win32/jvm.ini
@@ -0,0 +1,18 @@
+[Settings]
+NumFields=2
+
+[Field 1]
+Type=Label
+Text=Please select the path of a J2SE 5.0 or later JRE installed on your system. Note that if you have a 64-bit operating system, you must specify a 64-bit JRE:
+left=0
+right=300
+top=5
+bottom=30
+
+[Field 2]
+Type=DirRequest
+Left=0
+Right=-1
+Top=65
+Bottom=78
+
diff --git a/shim-webapp/packaging/win32/main.ico b/shim-webapp/packaging/win32/main.ico
new file mode 100644
index 0000000..dbf6e72
Binary files /dev/null and b/shim-webapp/packaging/win32/main.ico differ
diff --git a/shim-webapp/packaging/win32/shim.nsi b/shim-webapp/packaging/win32/shim.nsi
new file mode 100644
index 0000000..2e1f13e
--- /dev/null
+++ b/shim-webapp/packaging/win32/shim.nsi
@@ -0,0 +1,822 @@
+; Licensed to the FreeMED (ASF) under one or more
+; contributor license agreements.  See the NOTICE file distributed with
+; this work for additional information regarding copyright ownership.
+; The ASF licenses this file to You under the Apache License, Version 2.0
+; (the "License"); you may not use this file except in compliance with
+; the License.  You may obtain a copy of the License at
+;
+;     http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+
+; Tomcat script for Nullsoft Installer
+; $Id: tomcat.nsi 899134 2010-01-14 09:44:28Z rjung $
+
+  ;Compression options
+  CRCCheck on
+  SetCompressor /SOLID lzma
+
+  Name "FreeSHIM"
+  !define VERSION 0.1.1.2
+
+  ;Product information
+  VIAddVersionKey ProductName "FreeSHIM"
+  VIAddVersionKey CompanyName "FreeMED Software Foundation"
+  VIAddVersionKey LegalCopyright "Copyright (c) 1999-2012 FreeMED Software Foundation"
+  VIAddVersionKey FileDescription "FreeSHIM Installer"
+  VIAddVersionKey FileVersion "1.0"
+  VIAddVersionKey ProductVersion "0.1.1"
+  VIAddVersionKey Comments "freeshim.org"
+  VIAddVersionKey InternalName "freeshim-0.1.1.2-win32.exe"
+  VIProductVersion ${VERSION}
+  !define TOMCAT_VERSION 6.0.32
+
+!include "MUI.nsh"
+!include "StrFunc.nsh"
+${StrRep}
+  Var "JavaHome"
+
+
+
+;--------------------------------
+;Configuration
+
+  !define MUI_HEADERIMAGE
+  !define MUI_HEADERIMAGE_RIGHT
+  !define MUI_HEADERIMAGE_BITMAP header.bmp
+  !define MUI_WELCOMEFINISHPAGE_BITMAP side_left.bmp 
+  !define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\webapps\ROOT\RELEASE-NOTES.txt"
+  !define MUI_FINISHPAGE_RUN $INSTDIR\bin\tomcat6w.exe
+  !define MUI_FINISHPAGE_RUN_PARAMETERS //MR//Tomcat6
+  !define MUI_FINISHPAGE_NOREBOOTSUPPORT
+
+  !define MUI_ABORTWARNING
+
+  !define TEMP1 $R0
+  !define TEMP2 $R1
+
+  !define MUI_ICON tomcat.ico
+  !define MUI_UNICON tomcat.ico
+
+  ;General
+  OutFile freeshim-${version}-win32-setup.exe
+
+  ;Install Options pages
+  LangString TEXT_JVM_TITLE ${LANG_ENGLISH} "Java Virtual Machine"
+  LangString TEXT_JVM_SUBTITLE ${LANG_ENGLISH} "Java Virtual Machine path selection."
+  LangString TEXT_JVM_PAGETITLE ${LANG_ENGLISH} ": Java Virtual Machine path selection"
+
+  LangString TEXT_CONF_TITLE ${LANG_ENGLISH} "Configuration"
+  LangString TEXT_CONF_SUBTITLE ${LANG_ENGLISH} "Tomcat basic configuration."
+  LangString TEXT_CONF_PAGETITLE ${LANG_ENGLISH} ": Configuration Options"
+
+  ;Install Page order
+  !insertmacro MUI_PAGE_WELCOME
+  !insertmacro MUI_PAGE_LICENSE INSTALLLICENSE
+  !insertmacro MUI_PAGE_COMPONENTS
+  !insertmacro MUI_PAGE_DIRECTORY
+  Page custom SetConfiguration Void "$(TEXT_CONF_PAGETITLE)"
+  Page custom SetChooseJVM Void "$(TEXT_JVM_PAGETITLE)"
+  !insertmacro MUI_PAGE_INSTFILES
+  Page custom CheckUserType
+  !insertmacro MUI_PAGE_FINISH
+
+  ;Uninstall Page order
+  !insertmacro MUI_UNPAGE_CONFIRM
+  !insertmacro MUI_UNPAGE_INSTFILES
+
+  ;License dialog
+  ;LicenseData License.rtf
+
+  ;Component-selection page
+    ;Descriptions
+    LangString DESC_SecTomcat ${LANG_ENGLISH} "Install the Tomcat Servlet container."
+    LangString DESC_SecTomcatCore ${LANG_ENGLISH} "Install the Tomcat Servlet container core."
+    LangString DESC_SecTomcatService ${LANG_ENGLISH} "Automatically start Tomcat when the computer is started."
+    LangString DESC_SecTomcatNative ${LANG_ENGLISH} "Install APR based Tomcat native .dll for better performance and scalability in production environments."
+;    LangString DESC_SecTomcatSource ${LANG_ENGLISH} "Install the Tomcat source code."
+    LangString DESC_SecMenu ${LANG_ENGLISH} "Create a Start Menu program group for Tomcat."
+    LangString DESC_SecDocs ${LANG_ENGLISH} "Install the Tomcat documentation bundle. This includes documentation on the servlet container and its configuration options, on the Jasper JSP page compiler, as well as on the native webserver connectors."
+    LangString DESC_SecManager ${LANG_ENGLISH} "Install the Tomcat Manager administrative web application."
+    LangString DESC_SecHostManager ${LANG_ENGLISH} "Install the Tomcat Host Manager administrative web application."
+    LangString DESC_SecSHIM ${LANG_ENGLISH} "Install the FreeSHIM application."
+    LangString DESC_SecAdmin ${LANG_ENGLISH} "Installs the administration web application.";
+;    LangString DESC_SecWebapps ${LANG_ENGLISH} "Installs other utility web applications (WebDAV, balancer, etc)."
+
+  ;Language
+  !insertmacro MUI_LANGUAGE English
+
+  ;Folder-select dialog
+  InstallDir "$PROGRAMFILES\FreeMED\FreeSHIM"
+
+  ;Install types
+  InstType Normal
+  InstType Minimum
+  InstType Full
+
+  ; Main registry key
+  InstallDirRegKey HKLM "SOFTWARE\FreeMED\FreeSHIM" ""
+
+  !insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
+  ReserveFile "jvm.ini"
+  ReserveFile "config.ini"
+
+;--------------------------------
+;Installer Sections
+
+SubSection "Tomcat" SecTomcat
+
+Section "Core" SecTomcatCore
+
+  SectionIn 1 2 3 RO
+
+  IfSilent +2 0
+  Call checkJvm
+
+  SetOutPath $INSTDIR
+  File tomcat.ico
+  File apache-tomcat-${TOMCAT_VERSION}\LICENSE
+  File apache-tomcat-${TOMCAT_VERSION}\NOTICE
+  SetOutPath $INSTDIR\lib
+  File /r apache-tomcat-${TOMCAT_VERSION}\lib\*.*
+  SetOutPath $INSTDIR\logs
+  File /nonfatal /r apache-tomcat-${TOMCAT_VERSION}\logs\*.*
+  SetOutPath $INSTDIR\work
+  File /nonfatal /r apache-tomcat-${TOMCAT_VERSION}\work\*.*
+  SetOutPath $INSTDIR\temp
+  File /nonfatal /r apache-tomcat-${TOMCAT_VERSION}\temp\*.*
+  SetOutPath $INSTDIR\bin
+  File apache-tomcat-${TOMCAT_VERSION}\bin\bootstrap.jar
+  File apache-tomcat-${TOMCAT_VERSION}\bin\tomcat-juli.jar
+  SetOutPath $INSTDIR\conf
+  File apache-tomcat-${TOMCAT_VERSION}\conf\*.*
+  SetOutPath $INSTDIR\webapps\ROOT
+  File /r apache-tomcat-${TOMCAT_VERSION}\webapps\ROOT\*.*
+
+  Call configure
+  Call findJavaPath
+  Pop $2
+
+  IfSilent +2 0
+  !insertmacro MUI_INSTALLOPTIONS_READ $2 "jvm.ini" "Field 2" "State"
+
+  StrCpy "$JavaHome" $2
+  Call findJVMPath
+  Pop $2
+
+  DetailPrint "Using Jvm: $2"
+
+  SetOutPath $INSTDIR\bin
+  File apache-tomcat-${TOMCAT_VERSION}\bin\tomcat6w.exe
+
+  File /oname=tomcat6.exe apache-tomcat-${TOMCAT_VERSION}\bin\tomcat6.exe
+
+  ; Get the current platform x86 / AMD64 / IA64
+  ;Call FindCpuType
+  ;Pop $0
+  ;StrCmp $0 "x86" 0 +2
+  ;File /oname=tomcat6.exe apache-tomcat-${TOMCAT_VERSION}\bin\tomcat6.exe
+  ;StrCmp $0 "x64" 0 +2
+  ;File /oname=tomcat6.exe apache-tomcat-${TOMCAT_VERSION}\bin\x64\tomcat6.exe
+  ;StrCmp $0 "i64" 0 +2
+  ;File /oname=tomcat6.exe apache-tomcat-${TOMCAT_VERSION}\bin\i64\tomcat6.exe
+
+  InstallRetry:
+  ClearErrors
+  nsExec::ExecToLog '"$INSTDIR\bin\tomcat6.exe" //IS//Tomcat6 --DisplayName "Apache Tomcat 6" --Description "Apache Tomcat @VERSION@ Server - http://tomcat.apache.org/" --LogPath "$INSTDIR\logs" --Install "$INSTDIR\bin\tomcat6.exe" --Jvm "$2" --StartPath "$INSTDIR" --StopPath "$INSTDIR"'
+  Pop $0
+  StrCmp $0 "0" InstallOk
+    MessageBox MB_ABORTRETRYIGNORE|MB_ICONSTOP \
+      "Failed to install Tomcat6 service.$\r$\nCheck your settings and permissions.$\r$\nIgnore and continue anyway (not recommended)?" \
+       /SD IDIGNORE IDIGNORE InstallOk IDRETRY InstallRetry
+  Quit
+  InstallOk:
+  ClearErrors
+
+SectionEnd
+
+Section "Service" SecTomcatService
+
+  SectionIn 1 2 3
+
+  IfSilent 0 +3
+  Call findJavaPath
+  Pop $2
+
+  IfSilent +2 0
+  !insertmacro MUI_INSTALLOPTIONS_READ $2 "jvm.ini" "Field 2" "State"
+
+  StrCpy "$JavaHome" $2
+  Call findJVMPath
+  Pop $2
+
+  nsExec::ExecToLog '"$INSTDIR\bin\tomcat6.exe" //US//Tomcat6 --Startup auto'
+  ; Behave like Apache Httpd (put the icon in tray on login)
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Run" "ApacheTomcatMonitor" '"$INSTDIR\bin\tomcat6w.exe" //MS//Tomcat6'
+
+  ClearErrors
+
+SectionEnd
+
+Section "Native" SecTomcatNative
+
+  SectionIn 1 2 3 RO
+
+  SetOutPath $INSTDIR\bin
+
+  ; Topaz tablet HSB driver
+  File ..\..\..\shim-drivers\shim-driver-signature-topaz\native\win32\SigUsb.dll
+
+  File apache-tomcat-${TOMCAT_VERSION}\bin\tcnative-1.dll
+
+  ;Call FindCpuType
+  ;Pop $0
+  ;StrCmp $0 "x86" 0 +2
+  ;File apache-tomcat-${TOMCAT_VERSION}\bin\tcnative-1.dll
+  ;StrCmp $0 "x64" 0 +2
+  ;File /oname=tcnative-1.dll apache-tomcat-${TOMCAT_VERSION}\bin\x64\tcnative-1.dll
+  ;StrCmp $0 "i64" 0 +2
+  ;File /oname=tcnative-1.dll apache-tomcat-${TOMCAT_VERSION}\bin\i64\tcnative-1.dll
+
+  ClearErrors
+
+SectionEnd
+
+;Section "Source Code" SecTomcatSource
+;
+;  SectionIn 3
+;  SetOutPath $INSTDIR
+;  File /r src
+;
+;SectionEnd
+
+SubSectionEnd
+
+Section "Start Menu Items" SecMenu
+
+  SectionIn 1 2 3
+
+  !insertmacro MUI_INSTALLOPTIONS_READ $2 "jvm.ini" "Field 2" "State"
+
+  SetOutPath "$SMPROGRAMS\Apache Tomcat @VERSION_MAJOR_MINOR@"
+
+  CreateShortCut "$SMPROGRAMS\Apache Tomcat @VERSION_MAJOR_MINOR@\Tomcat Home Page.lnk" \
+                 "http://tomcat.apache.org/"
+
+  CreateShortCut "$SMPROGRAMS\Apache Tomcat @VERSION_MAJOR_MINOR@\Welcome.lnk" \
+                 "http://localhost:$R0/"
+
+;  IfFileExists "$INSTDIR\webapps\admin" 0 NoAdminApp
+;
+;  CreateShortCut "$SMPROGRAMS\Apache Tomcat @VERSION_MAJOR_MINOR@\Tomcat Administration.lnk" \
+;                 "http://localhost:$R0/admin/"
+;NoAdminApp:
+
+  IfFileExists "$INSTDIR\webapps\manager" 0 NoManagerApp
+
+  CreateShortCut "$SMPROGRAMS\FreeSHIM\Tomcat Manager.lnk" \
+                 "http://localhost:$R0/manager/html"
+
+NoManagerApp:
+
+  IfFileExists "$INSTDIR\webapps\webapps\tomcat-docs" 0 NoDocumentaion
+
+  CreateShortCut "$SMPROGRAMS\FreeSHIM\Tomcat Documentation.lnk" \
+                 "$INSTDIR\webapps\tomcat-docs\index.html"
+
+NoDocumentaion:
+
+  CreateShortCut "$SMPROGRAMS\FreeSHIM\Uninstall FreeSHIM.lnk" \
+                 "$INSTDIR\Uninstall.exe"
+
+  CreateShortCut "$SMPROGRAMS\FreeSHIM\Program Directory.lnk" \
+                 "$INSTDIR"
+
+  CreateShortCut "$SMPROGRAMS\FreeSHIM\Monitor Tomcat.lnk" \
+                 "$INSTDIR\bin\tomcat6w.exe" \
+                 '//MS//Tomcat6' \
+                 "$INSTDIR\tomcat.ico" 0 SW_SHOWNORMAL
+
+  CreateShortCut "$SMPROGRAMS\FreeSHIM\Configure Tomcat.lnk" \
+                 "$INSTDIR\bin\tomcat6w.exe" \
+                 '//ES//Tomcat6' \
+                 "$INSTDIR\tomcat.ico" 0 SW_SHOWNORMAL
+
+SectionEnd
+
+Section "Documentation" SecDocs
+
+  SectionIn 1 3
+  SetOutPath $INSTDIR\webapps\docs
+  File /r apache-tomcat-${TOMCAT_VERSION}\webapps\docs\*.*
+
+SectionEnd
+
+Section "Manager" SecManager
+
+  SectionIn 1 3
+
+  SetOverwrite on
+  SetOutPath $INSTDIR\webapps\manager
+  File /r apache-tomcat-${TOMCAT_VERSION}\webapps\manager\*.*
+
+SectionEnd
+
+Section "Host Manager" SecHostManager
+
+  SectionIn 3
+
+  SetOverwrite on
+  SetOutPath $INSTDIR\webapps\host-manager
+  File /r apache-tomcat-${TOMCAT_VERSION}\webapps\host-manager\*.*
+
+SectionEnd
+
+Section "SHIM" SecSHIM
+
+  SectionIn 1 2 3 RO
+
+  SetOverwrite on
+  SetOutPath $INSTDIR\webapps
+  File /r ..\..\target\shim.war
+
+SectionEnd
+
+;Section "Administration" SecAdmin
+;
+;  SectionIn 3
+;
+;  SetOutPath $INSTDIR\webapps
+;  File /r webapps\admin
+;  SetOutPath $INSTDIR\conf\Catalina\localhost
+;  File conf\Catalina\localhost\admin.xml
+;
+;SectionEnd
+
+;Section "Webapps" SecWebapps
+;
+;  SectionIn 3
+;
+;  SetOutPath $INSTDIR\webapps
+;  File /nonfatal /r webapps\balancer
+;  File /nonfatal /r webapps\webdav
+;
+;SectionEnd
+
+;Section "Compatibility" SecCompat
+;
+;  SetOutPath $INSTDIR
+;  File /oname=bin\jmx.jar ..\compat\bin\jmx.jar
+;  File /oname=common\endorsed\xercesImpl.jar ..\compat\common\endorsed\xercesImpl.jar
+;  File /oname=common\endorsed\xml-apis.jar  ..\compat\common\endorsed\xml-apis.jar
+;
+;SectionEnd
+
+Section -post
+  nsExec::ExecToLog '"$INSTDIR\bin\tomcat6.exe" //US//Tomcat6 --Classpath "$INSTDIR\bin\bootstrap.jar" --StartClass org.apache.catalina.startup.Bootstrap --StopClass org.apache.catalina.startup.Bootstrap --StartParams start --StopParams stop  --StartMode jvm --StopMode jvm'
+  nsExec::ExecToLog '"$INSTDIR\bin\tomcat6.exe" //US//Tomcat6 --JvmOptions "-Dcatalina.home=$INSTDIR#-Dcatalina.base=$INSTDIR#-Djava.endorsed.dirs=$INSTDIR\endorsed#-Djava.io.tmpdir=$INSTDIR\temp#-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager#-Djava.util.logging.config.file=$INSTDIR\conf\logging.properties" --StdOutput auto --StdError auto'
+
+  WriteUninstaller "$INSTDIR\Uninstall.exe"
+
+  WriteRegStr HKLM "SOFTWARE\FreeMED\FreeSHIM" "InstallPath" $INSTDIR
+  WriteRegStr HKLM "SOFTWARE\FreeMED\FreeSHIM" "Version" @VERSION@
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\FreeSHIM" \
+                   "DisplayName" "FreeSHIM (remove only)"
+  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\FreeSHIM" \
+                   "UninstallString" '"$INSTDIR\Uninstall.exe"'
+
+SectionEnd
+
+Function .onInit
+  ;Reset install dir for 64-bit
+  ExpandEnvStrings $0 "%PROGRAMW6432%"
+  StrCmp $0 "%PROGRAMW6432%" +2 0
+  StrCpy $INSTDIR "$0\FreeMED\FreeSHIM"
+
+  ;Extract Install Options INI Files
+  !insertmacro MUI_INSTALLOPTIONS_EXTRACT "config.ini"
+  !insertmacro MUI_INSTALLOPTIONS_EXTRACT "jvm.ini"
+
+FunctionEnd
+
+Function SetChooseJVM
+  !insertmacro MUI_HEADER_TEXT "$(TEXT_JVM_TITLE)" "$(TEXT_JVM_SUBTITLE)"
+  Call findJavaPath
+  Pop $3
+  !insertmacro MUI_INSTALLOPTIONS_WRITE "jvm.ini" "Field 2" "State" $3
+  !insertmacro MUI_INSTALLOPTIONS_DISPLAY "jvm.ini"
+FunctionEnd
+
+Function SetConfiguration
+  !insertmacro MUI_HEADER_TEXT "$(TEXT_CONF_TITLE)" "$(TEXT_CONF_SUBTITLE)"
+
+  SectionGetFlags ${SecManager} $0
+  IntOp $0 $0 & ${SF_SELECTED}
+  IntCmp $0 0 0 Enable Enable
+  SectionGetFlags ${SecHostManager} $0
+  IntOp $0 $0 & ${SF_SELECTED}
+  IntCmp $0 0 Disable 0 0
+
+Enable:
+  ; Enable the user and password controls if the manager or host-manager app is
+  ; being installed
+  !insertmacro MUI_INSTALLOPTIONS_READ $0 "config.ini" "Field 5" "HWND"
+  !insertmacro MUI_INSTALLOPTIONS_WRITE "config.ini" "Field 5" "Flags" ""
+  EnableWindow $0 1
+  !insertmacro MUI_INSTALLOPTIONS_READ $0 "config.ini" "Field 7" "HWND"
+  !insertmacro MUI_INSTALLOPTIONS_WRITE "config.ini" "Field 7" "Flags" ""
+  EnableWindow $0 1
+  Goto Display
+
+Disable:
+  ; Disable the user and password controls if neither the manager nor
+  ; host-manager app is being installed
+  !insertmacro MUI_INSTALLOPTIONS_READ $0 "config.ini" "Field 5" "HWND"
+  !insertmacro MUI_INSTALLOPTIONS_WRITE "config.ini" "Field 5" "Flags" "DISABLED"
+  EnableWindow $0 0
+  !insertmacro MUI_INSTALLOPTIONS_READ $0 "config.ini" "Field 7" "HWND"
+  !insertmacro MUI_INSTALLOPTIONS_WRITE "config.ini" "Field 7" "Flags" "DISABLED"
+  EnableWindow $0 0
+  ; Clear the values
+  !insertmacro MUI_INSTALLOPTIONS_WRITE "config.ini" "Field 5" "State" ""
+  !insertmacro MUI_INSTALLOPTIONS_WRITE "config.ini" "Field 7" "State" ""
+
+Display:
+  !insertmacro MUI_INSTALLOPTIONS_DISPLAY "config.ini"
+
+FunctionEnd
+
+Function Void
+FunctionEnd
+
+;--------------------------------
+;Descriptions
+
+!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+  !insertmacro MUI_DESCRIPTION_TEXT ${SecTomcat} $(DESC_SecTomcat)
+  !insertmacro MUI_DESCRIPTION_TEXT ${SecTomcatCore} $(DESC_SecTomcatCore)
+  !insertmacro MUI_DESCRIPTION_TEXT ${SecTomcatService} $(DESC_SecTomcatService)
+  !insertmacro MUI_DESCRIPTION_TEXT ${SecTomcatNative} $(DESC_SecTomcatNative)
+;  !insertmacro MUI_DESCRIPTION_TEXT ${SecTomcatSource} $(DESC_SecTomcatSource)
+;  !insertmacro MUI_DESCRIPTION_TEXT ${SecCompat} $(DESC_SecCompat)
+  !insertmacro MUI_DESCRIPTION_TEXT ${SecMenu} $(DESC_SecMenu)
+  !insertmacro MUI_DESCRIPTION_TEXT ${SecDocs} $(DESC_SecDocs)
+  !insertmacro MUI_DESCRIPTION_TEXT ${SecManager} $(DESC_SecManager)
+  !insertmacro MUI_DESCRIPTION_TEXT ${SecHostManager} $(DESC_SecHostManager)
+  !insertmacro MUI_DESCRIPTION_TEXT ${SecSHIM} $(DESC_SecSHIM)
+;  !insertmacro MUI_DESCRIPTION_TEXT ${SecAdmin} $(DESC_SecAdmin)
+;  !insertmacro MUI_DESCRIPTION_TEXT ${SecWebapps} $(DESC_SecWebapps)
+!insertmacro MUI_FUNCTION_DESCRIPTION_END
+
+; =====================
+; FindCpuType Function
+; =====================
+;
+; Find the CPU used on the system, and put the result on the top of the
+; stack
+;
+Function FindCpuType
+
+  ClearErrors
+  ; Default CPU is always x86
+  StrCpy $1 "x86"
+  ExpandEnvStrings $0 "%PROCESSOR_ARCHITEW6432%"
+  StrCmp $0 "%PROCESSOR_ARCHITEW6432%" +5 0
+  StrCmp $0 "IA64" 0 +3
+  StrCpy $1 "i64"
+  Goto FoundCpu
+  StrCpy $1 "x64"
+
+FoundCpu:
+  ; Put the result in the stack
+  Push $1
+
+FunctionEnd
+
+; =====================
+; CheckUserType Function
+; =====================
+;
+; Check the user type, and warn if it's not an administrator.
+; Taken from Examples/UserInfo that ships with NSIS.
+Function CheckUserType
+  ClearErrors
+  UserInfo::GetName
+  IfErrors Win9x
+  Pop $0
+  UserInfo::GetAccountType
+  Pop $1
+  StrCmp $1 "Admin" 0 +3
+    ; This is OK, do nothing
+    Goto done
+
+    MessageBox MB_OK|MB_ICONEXCLAMATION 'Note: the current user is not an administrator. \
+               To run FreeSHIM as a Windows service, you must be an administrator. \
+               You can still run FreeSHIM from the command-line as this type of user.'
+    Goto done
+
+  Win9x:
+    # This one means you don't need to care about admin or
+    # not admin because Windows 9x doesn't either
+    MessageBox MB_OK "Error! This DLL can't run under Windows 9x!"
+
+  done:
+FunctionEnd
+
+
+; =====================
+; FindJavaPath Function
+; =====================
+;
+; Find the JAVA_HOME used on the system, and put the result on the top of the
+; stack
+; Will return an empty string if the path cannot be determined
+;
+Function findJavaPath
+
+  ;ClearErrors
+
+  ;ReadEnvStr $1 JAVA_HOME
+
+  ;IfErrors 0 FoundJDK
+
+  ClearErrors
+
+  ; Use the 64-bit registry on 64-bit machines
+  ExpandEnvStrings $0 "%PROGRAMW6432%"
+  StrCmp $0 "%PROGRAMW6432%" +2 0
+  SetRegView 64
+
+  ReadRegStr $2 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" "CurrentVersion"
+  ReadRegStr $1 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment\$2" "JavaHome"
+  ReadRegStr $3 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment\$2" "RuntimeLib"
+
+  ;FoundJDK:
+
+  IfErrors 0 NoErrors
+  StrCpy $1 ""
+
+NoErrors:
+
+  ClearErrors
+
+  ; Put the result in the stack
+  Push $1
+
+FunctionEnd
+
+
+; ====================
+; FindJVMPath Function
+; ====================
+;
+; Find the full JVM path, and put the result on top of the stack
+; Argument: JVM base path (result of findJavaPath)
+; Will return an empty string if the path cannot be determined
+;
+Function findJVMPath
+
+  ClearErrors
+  
+  ;Step one: Is this a JRE path (Program Files\Java\XXX)
+  StrCpy $1 "$JavaHome"
+  
+  StrCpy $2 "$1\bin\hotspot\jvm.dll"
+  IfFileExists "$2" FoundJvmDll
+  StrCpy $2 "$1\bin\server\jvm.dll"
+  IfFileExists "$2" FoundJvmDll
+  StrCpy $2 "$1\bin\client\jvm.dll"  
+  IfFileExists "$2" FoundJvmDll
+  StrCpy $2 "$1\bin\classic\jvm.dll"
+  IfFileExists "$2" FoundJvmDll
+
+  ;Step two: Is this a JDK path (Program Files\XXX\jre)
+  StrCpy $1 "$JavaHome\jre"
+  
+  StrCpy $2 "$1\bin\hotspot\jvm.dll"
+  IfFileExists "$2" FoundJvmDll
+  StrCpy $2 "$1\bin\server\jvm.dll"
+  IfFileExists "$2" FoundJvmDll
+  StrCpy $2 "$1\bin\client\jvm.dll"  
+  IfFileExists "$2" FoundJvmDll
+  StrCpy $2 "$1\bin\classic\jvm.dll"
+  IfFileExists "$2" FoundJvmDll
+
+  ClearErrors
+  ;Step tree: Read defaults from registry
+  
+  ReadRegStr $1 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" "CurrentVersion"
+  ReadRegStr $2 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment\$1" "RuntimeLib"
+  
+  IfErrors 0 FoundJvmDll
+  StrCpy $2 ""
+
+  FoundJvmDll:
+  ClearErrors
+
+  ; Put the result in the stack
+  Push $2
+
+FunctionEnd
+
+
+; ====================
+; CheckJvm Function
+; ====================
+;
+Function checkJvm
+
+  !insertmacro MUI_INSTALLOPTIONS_READ $3 "jvm.ini" "Field 2" "State"
+  IfFileExists "$3\bin\java.exe" NoErrors1
+  MessageBox MB_OK|MB_ICONSTOP "No Java Virtual Machine found in folder:$\r$\n$3"
+  Quit
+NoErrors1:
+  StrCpy "$JavaHome" $3
+  Call findJVMPath
+  Pop $4
+  StrCmp $4 "" 0 NoErrors2
+  MessageBox MB_OK|MB_ICONSTOP "No Java Virtual Machine found in folder:$\r$\n$3"
+  Quit
+NoErrors2:
+
+FunctionEnd
+
+; ==================
+; Configure Function
+; ==================
+;
+; Display the configuration dialog boxes, read the values entered by the user,
+; and build the configuration files
+;
+Function configure
+
+  !insertmacro MUI_INSTALLOPTIONS_READ $R0 "config.ini" "Field 2" "State"
+  !insertmacro MUI_INSTALLOPTIONS_READ $R1 "config.ini" "Field 5" "State"
+  !insertmacro MUI_INSTALLOPTIONS_READ $R2 "config.ini" "Field 7" "State"
+
+  IfSilent 0 +2
+  StrCpy $R0 '8180'
+
+  StrCpy $R4 'port="$R0"'
+  StrCpy $R5 ''
+
+  IfSilent Silent 0
+
+  ; Escape XML
+  Push $R1
+  Call xmlEscape
+  Pop $R1
+  Push $R2
+  Call xmlEscape
+  Pop $R2
+  
+  StrCmp $R1 "" +4 0  ; Blank user - do not add anything to tomcat-users.xml
+  StrCmp $R2 "" +3 0  ; Blank password - do not add anything to tomcat-users.xml
+  StrCpy $R5 '<user name="$R1" password="$R2" roles="admin,manager,default" />'
+  DetailPrint 'Admin user added: "$R1"'
+  
+Silent:
+  DetailPrint 'HTTP/1.1 Connector configured on port "$R0"'
+
+  SetOutPath $TEMP
+  File /r confinstall
+
+  ; Build final server.xml
+  Delete "$INSTDIR\conf\server.xml"
+  FileOpen $R9 "$INSTDIR\conf\server.xml" w
+
+  Push "$TEMP\confinstall\server_1.xml"
+  Call copyFile
+  FileWrite $R9 $R4
+  Push "$TEMP\confinstall\server_2.xml"
+  Call copyFile
+
+  FileClose $R9
+
+  DetailPrint "server.xml written"
+
+  ; Build final tomcat-users.xml
+  
+  Delete "$INSTDIR\conf\tomcat-users.xml"
+  FileOpen $R9 "$INSTDIR\conf\tomcat-users.xml" w
+  ; File will be written using current windows codepage
+  System::Call 'Kernel32::GetACP() i .r18'
+  StrCmp $R8 "932" 0 +3
+    ; Special case where Java uses non-standard name for character set
+    FileWrite $R9 "<?xml version='1.0' encoding='ms$R8'?>$\r$\n"
+    Goto +2
+    FileWrite $R9 "<?xml version='1.0' encoding='cp$R8'?>$\r$\n"
+  Push "$TEMP\confinstall\tomcat-users_1.xml"
+  Call copyFile
+  FileWrite $R9 $R5
+  Push "$TEMP\confinstall\tomcat-users_2.xml"
+  Call copyFile
+
+  FileClose $R9
+
+  DetailPrint "tomcat-users.xml written"
+
+  RMDir /r "$TEMP\confinstall"
+
+FunctionEnd
+
+
+Function xmlEscape
+  Pop $0
+  ${StrRep} $0 $0 "&" "&"
+  ${StrRep} $0 $0 "$\"" """
+  ${StrRep} $0 $0 "<" "<"
+  ${StrRep} $0 $0 ">" ">"
+  Push $0
+FunctionEnd
+
+
+; =================
+; CopyFile Function
+; =================
+;
+; Copy specified file contents to $R9
+;
+Function copyFile
+
+  ClearErrors
+
+  Pop $0
+
+  FileOpen $1 $0 r
+
+ NoError:
+
+  FileRead $1 $2
+  IfErrors EOF 0
+  FileWrite $R9 $2
+
+  IfErrors 0 NoError
+
+ EOF:
+
+  FileClose $1
+
+  ClearErrors
+
+FunctionEnd
+
+
+;--------------------------------
+;Uninstaller Section
+
+Section Uninstall
+
+  Delete "$INSTDIR\modern.exe"
+  Delete "$INSTDIR\Uninstall.exe"
+
+  ; Stop FreeSHIM service monitor if running
+  nsExec::ExecToLog '"$INSTDIR\bin\tomcat6w.exe" //MQ//Tomcat6'
+  ; Delete Tomcat service
+  nsExec::ExecToLog '"$INSTDIR\bin\tomcat6.exe" //DS//Tomcat6'
+  ClearErrors
+
+  DeleteRegKey HKCR "JSPFile"
+  DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\FreeSHIM"
+  DeleteRegKey HKLM "SOFTWARE\FreeMED\FreeSHIM"
+  DeleteRegValue HKLM "Software\Microsoft\Windows\CurrentVersion\Run" "ApacheTomcatMonitor"
+  RMDir /r "$SMPROGRAMS\FreeSHIM"
+  Delete "$INSTDIR\tomcat.ico"
+  Delete "$INSTDIR\LICENSE"
+  Delete "$INSTDIR\NOTICE"
+  RMDir /r "$INSTDIR\bin"
+  RMDir /r "$INSTDIR\lib"
+  Delete "$INSTDIR\conf\*.dtd"
+  RMDir "$INSTDIR\logs"
+;  RMDir /r "$INSTDIR\webapps\balancer"
+  RMDir /r "$INSTDIR\webapps\docs"
+  RMDir /r "$INSTDIR\webapps\shim"
+;  RMDir /r "$INSTDIR\webapps\webdav"
+  RMDir /r "$INSTDIR\work"
+  RMDir /r "$INSTDIR\temp"
+  RMDir "$INSTDIR"
+
+  IfSilent Removed 0
+
+  ; if $INSTDIR was removed, skip these next ones
+  IfFileExists "$INSTDIR" 0 Removed 
+    MessageBox MB_YESNO|MB_ICONQUESTION \
+      "Remove all files in your Tomcat @VERSION_MAJOR_MINOR@ directory? (If you have anything  \
+ you created that you want to keep, click No)" IDNO Removed
+    RMDir /r "$INSTDIR\webapps\ROOT" ; this would be skipped if the user hits no
+    RMDir "$INSTDIR\webapps"
+    Delete "$INSTDIR\*.*" 
+    RMDir /r "$INSTDIR"
+    Sleep 500
+    IfFileExists "$INSTDIR" 0 Removed 
+      MessageBox MB_OK|MB_ICONEXCLAMATION \
+                 "Note: $INSTDIR could not be removed."
+  Removed:
+
+SectionEnd
+
+;eof
diff --git a/shim-webapp/packaging/win32/side_left.bmp b/shim-webapp/packaging/win32/side_left.bmp
new file mode 100644
index 0000000..3ba7dbc
Binary files /dev/null and b/shim-webapp/packaging/win32/side_left.bmp differ
diff --git a/shim-webapp/packaging/win32/tickno.bmp b/shim-webapp/packaging/win32/tickno.bmp
new file mode 100644
index 0000000..64a6749
Binary files /dev/null and b/shim-webapp/packaging/win32/tickno.bmp differ
diff --git a/shim-webapp/packaging/win32/tickyes.bmp b/shim-webapp/packaging/win32/tickyes.bmp
new file mode 100644
index 0000000..7b5d420
Binary files /dev/null and b/shim-webapp/packaging/win32/tickyes.bmp differ
diff --git a/shim-webapp/packaging/win32/tomcat.ico b/shim-webapp/packaging/win32/tomcat.ico
new file mode 100644
index 0000000..6c5bd2c
Binary files /dev/null and b/shim-webapp/packaging/win32/tomcat.ico differ
diff --git a/shim-webapp/packaging/win32/uninst.ico b/shim-webapp/packaging/win32/uninst.ico
new file mode 100644
index 0000000..ada4df8
Binary files /dev/null and b/shim-webapp/packaging/win32/uninst.ico differ
diff --git a/shim-webapp/packaging/win32/welcome.bin.html b/shim-webapp/packaging/win32/welcome.bin.html
new file mode 100644
index 0000000..e309123
--- /dev/null
+++ b/shim-webapp/packaging/win32/welcome.bin.html
@@ -0,0 +1,87 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML><HEAD><TITLE>Apache Tomcat @VERSION@</TITLE>
+<META http-equiv=Content-Type content="text/html;charset=ISO-8859-1">
+</HEAD>
+<BODY>
+<P>
+<H3>Apache Tomcat @VERSION@</H3>
+<P></P>
+<p>Useful references:</p>
+<ul>
+<li><a href="../RELEASE-NOTES">Release notes</a>, with important information 
+about known issues</li>
+<li><a href="http://tomcat.apache.org/tomcat-@VERSION_MAJOR_MINOR@-doc/changelog.html">Changelog</a></li>
+</ul>
+
+<p><b>NOTE: The tar files in this distribution use GNU tar extensions, 
+and must be untarred with a GNU compatible version of tar. The version 
+of <CODE>tar</CODE> on Solaris and Mac OS X will not work with 
+these files.</b></P>
+
+<p><font color="red">Tomcat @VERSION_MAJOR_MINOR@ requires JRE 5.0 or later.  Read the 
+RELEASE-NOTES and the RUNNING.txt file in the distribution for more details.
+</font></p>
+
+<h4>Packaging Details (or "What Should I Download?")</h4>
+<dl>
+<dt><b>bin/</b></dt>
+<dd><dl>
+  <dt>apache-tomcat-[version].zip or .tar.gz</dt>
+    <dd>Base distribution. These distributions do not include the Windows
+    service wrapper nor the compiled APR/native library for Windows.</dd>
+  <dt>apache-tomcat-[version].exe</dt>
+    <dd>32-bit/64-bit Windows installer for Tomcat.   Please note that while this
+    distribution includes the vast majority of the base distribution, some of the
+    command-line scripts for launching Tomcat are not included.  This distribution
+    is intended for those users planning to launch Tomcat through the Windows
+    shortcuts or services.</dd>
+  <dt>apache-tomcat-[version]-windows-x86.zip</dt>
+    <dd>32-bit Windows specific distribution that includes the Windows service
+    wrapper and the compiled APR/native library for use with 32-bit JVMs on both
+    32 and 64 bit Windows platforms.</dd>
+  <dt>apache-tomcat-[version]-windows-x64.zip</dt>
+    <dd>64-bit Windows specific distribution that includes the Windows service
+    wrapper and the compiled APR/native library for use with 64-bit JVMs on
+    x64 Windows platforms.</dd>
+  <dt>apache-tomcat-[version]-windows-i64.zip</dt>
+    <dd>64-bit Windows specific distribution that includes the Windows service
+    wrapper and the compiled APR/native library for use with 64-bit JVMs on
+    Itanium 64-bit Windows platforms.</dd>
+  <dt>apache-tomcat-[version]-deployer.zip or .tar.gz</dt>
+    <dd>The standalone Tomcat Web Application Deployer.</dd>
+  <dt>apache-tomcat-[version]-fulldocs.tar.gz</dt>
+    <dd>The Tomcat documentation bundle, including complete javadocs.</dd>
+</dl></dd>
+<dt><b>bin/extras/</b></dt>
+<dd>Additional components. See
+  <a href="http://tomcat.apache.org/tomcat-@VERSION_MAJOR_MINOR@-doc/extras.html">documentation</a>.</dd>
+<dt><b>src/</b></dt>
+<dd><dl>
+  <dt>apache-tomcat-[version].zip or .tar.gz</dt>
+    <dd>The source code. See
+    <a href="http://tomcat.apache.org/tomcat-@VERSION_MAJOR_MINOR@-doc/building.html">building instructions</a>.</dd>
+</dl></dd>
+</dl>
+
+<P>Thank you for using <A href="http://tomcat.apache.org/">Tomcat</A>!. 
+</P>
+<P><B>The Apache Tomcat Project</B> <BR><A 
+href="http://tomcat.apache.org/">http://tomcat.apache.org/</A> </P>
+<P>
+<P></P></BODY></HTML>
diff --git a/shim-webapp/packaging/win32/welcome.main.html b/shim-webapp/packaging/win32/welcome.main.html
new file mode 100644
index 0000000..b9067ed
--- /dev/null
+++ b/shim-webapp/packaging/win32/welcome.main.html
@@ -0,0 +1,87 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML><HEAD><TITLE>Apache Tomcat @VERSION@</TITLE>
+<META http-equiv=Content-Type content="text/html;charset=ISO-8859-1">
+</HEAD>
+<BODY>
+<P>
+<H3>Apache Tomcat @VERSION@</H3>
+<P></P>
+<p>Useful references:</p>
+<ul>
+<li><a href="RELEASE-NOTES">Release notes</a>, with important information 
+about known issues</li>
+<li><a href="http://tomcat.apache.org/tomcat-@VERSION_MAJOR_MINOR@-doc/changelog.html">Changelog</a></li>
+</ul>
+
+<p><b>NOTE: The tar files in this distribution use GNU tar extensions, 
+and must be untarred with a GNU compatible version of tar. The version 
+of <CODE>tar</CODE> on Solaris and Mac OS X will not work with 
+these files.</b></P>
+
+<p><font color="red">Tomcat @VERSION_MAJOR_MINOR@ requires JRE 5.0 or later.  Read the 
+RELEASE-NOTES and the RUNNING.txt file in the distribution for more details.
+</font></p>
+
+<h4>Packaging Details (or "What Should I Download?")</h4>
+<dl>
+<dt><b>bin/</b></dt>
+<dd><dl>
+  <dt>apache-tomcat-[version].zip or .tar.gz</dt>
+    <dd>Base distribution. These distributions do not include the Windows
+    service wrapper nor the compiled APR/native library for Windows.</dd>
+  <dt>apache-tomcat-[version].exe</dt>
+    <dd>32-bit/64-bit Windows installer for Tomcat.   Please note that while this
+    distribution includes the vast majority of the base distribution, some of the
+    command-line scripts for launching Tomcat are not included.  This distribution
+    is intended for those users planning to launch Tomcat through the Windows
+    shortcuts or services.</dd>
+  <dt>apache-tomcat-[version]-windows-x86.zip</dt>
+    <dd>32-bit Windows specific distribution that includes the Windows service
+    wrapper and the compiled APR/native library for use with 32-bit JVMs on both
+    32 and 64 bit Windows platforms.</dd>
+  <dt>apache-tomcat-[version]-windows-x64.zip</dt>
+    <dd>64-bit Windows specific distribution that includes the Windows service
+    wrapper and the compiled APR/native library for use with 64-bit JVMs on
+    x64 Windows platforms.</dd>
+  <dt>apache-tomcat-[version]-windows-i64.zip</dt>
+    <dd>64-bit Windows specific distribution that includes the Windows service
+    wrapper and the compiled APR/native library for use with 64-bit JVMs on
+    Itanium 64-bit Windows platforms.</dd>
+  <dt>apache-tomcat-[version]-deployer.zip or .tar.gz</dt>
+    <dd>The standalone Tomcat Web Application Deployer.</dd>
+  <dt>apache-tomcat-[version]-fulldocs.tar.gz</dt>
+    <dd>The Tomcat documentation bundle, including complete javadocs.</dd>
+</dl></dd>
+<dt><b>bin/extras/</b></dt>
+<dd>Additional components. See
+  <a href="http://tomcat.apache.org/tomcat-@VERSION_MAJOR_MINOR@-doc/extras.html">documentation</a>.</dd>
+<dt><b>src/</b></dt>
+<dd><dl>
+  <dt>apache-tomcat-[version].zip or .tar.gz</dt>
+    <dd>The source code. See
+    <a href="http://tomcat.apache.org/tomcat-@VERSION_MAJOR_MINOR@-doc/building.html">building instructions</a>.</dd>
+</dl></dd>
+</dl>
+
+<P>Thank you for using <A href="http://tomcat.apache.org/">Tomcat</A>!. 
+</P>
+<P><B>The Apache Tomcat Project</B> <BR><A 
+href="http://tomcat.apache.org/">http://tomcat.apache.org/</A> </P>
+<P>
+<P></P></BODY></HTML>
diff --git a/shim-webapp/pom.xml b/shim-webapp/pom.xml
new file mode 100644
index 0000000..6565233
--- /dev/null
+++ b/shim-webapp/pom.xml
@@ -0,0 +1,146 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>org.freemedsoftware</groupId>
+	<artifactId>shim-webapp</artifactId>
+	<packaging>war</packaging>
+	<version>0.1.1</version>
+	<name>shim-webapp</name>
+	<url>http://freemedsoftware.org</url>
+	<dependencies>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.8.2</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>log4j</groupId>
+			<artifactId>log4j</artifactId>
+			<version>1.2.16</version>
+			<type>jar</type>
+			<scope>compile</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.apache.cxf</groupId>
+			<artifactId>cxf-bundle</artifactId>
+			<version>2.6.0</version>
+			<scope>compile</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.apache.cxf</groupId>
+			<artifactId>cxf-bundle-jaxrs</artifactId>
+			<version>2.6.0</version>
+			<scope>compile</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.freemedsoftware</groupId>
+			<artifactId>shim-library</artifactId>
+			<version>${version}</version>
+			<type>jar</type>
+			<scope>compile</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.freemedsoftware</groupId>
+			<artifactId>shim-driver-label-escpos</artifactId>
+			<version>${version}</version>
+			<type>jar</type>
+			<scope>compile</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.freemedsoftware</groupId>
+			<artifactId>shim-driver-signature-topaz</artifactId>
+			<version>${version}</version>
+			<type>jar</type>
+			<scope>compile</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.freemedsoftware</groupId>
+			<artifactId>shim-driver-signature-dummy</artifactId>
+			<version>${version}</version>
+			<type>jar</type>
+			<scope>compile</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.freemedsoftware</groupId>
+			<artifactId>shim-driver-lab-clinitek50</artifactId>
+			<version>${version}</version>
+			<type>jar</type>
+			<scope>compile</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.freemedsoftware</groupId>
+			<artifactId>shim-driver-lab-microlab3500</artifactId>
+			<version>${version}</version>
+			<type>jar</type>
+			<scope>compile</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.freemedsoftware</groupId>
+			<artifactId>shim-driver-dosing-scilog</artifactId>
+			<version>${version}</version>
+			<type>jar</type>
+			<scope>compile</scope>
+		</dependency>
+		<dependency>
+			<groupId>commons-configuration</groupId>
+			<artifactId>commons-configuration</artifactId>
+			<version>1.8</version>
+			<type>jar</type>
+			<scope>compile</scope>
+		</dependency>
+	</dependencies>
+
+	<repositories>
+		<repository>
+			<id>maven2-repository.dev.java.net</id>
+			<name>Java.net Repository for Maven 2</name>
+			<url>http://download.java.net/maven/2/</url>
+		</repository>
+	</repositories>
+
+	<pluginRepositories>
+		<pluginRepository>
+			<id>maven2-repository.dev.java.net</id>
+			<url>http://download.java.net/maven/2/</url>
+		</pluginRepository>
+	</pluginRepositories>
+
+	<build>
+		<finalName>shim</finalName>
+		<plugins>
+			<!-- Compile -->
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>2.3.2</version>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+
+			<plugin>
+				<groupId>org.mortbay.jetty</groupId>
+				<artifactId>maven-jetty-plugin</artifactId>
+				<version>6.1.26</version>
+				<configuration>
+					<scanIntervalSeconds>10</scanIntervalSeconds>
+					<stopPort>9999</stopPort>
+					<userRealms>
+						<userRealm implementation="org.mortbay.jetty.security.HashUserRealm">
+							<name>default</name>
+							<config>jetty-realm.properties</config>
+						</userRealm>
+					</userRealms>
+				</configuration>
+			</plugin>
+
+		</plugins>
+	</build>
+
+</project>
diff --git a/shim-webapp/src/main/java/org/freemedsoftware/shim/Configuration.java b/shim-webapp/src/main/java/org/freemedsoftware/shim/Configuration.java
new file mode 100644
index 0000000..df50d67
--- /dev/null
+++ b/shim-webapp/src/main/java/org/freemedsoftware/shim/Configuration.java
@@ -0,0 +1,124 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.shim;
+
+import java.io.File;
+
+import org.apache.commons.configuration.CompositeConfiguration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
+import org.apache.log4j.Logger;
+
+public class Configuration {
+
+	public static String DEFAULT_CONFIG = "/WEB-INF/shim-default.properties";
+	public static String OVERRIDE_CONFIG = System
+			.getProperty("shim.properties");
+
+	protected static CompositeConfiguration compositeConfiguration = null;
+
+	static final Logger log = Logger.getLogger(Configuration.class);
+
+	protected static MasterControlServlet servletContext = null;
+
+	/**
+	 * Get servlet object.
+	 * 
+	 * @return
+	 */
+	public static MasterControlServlet getServletContext() {
+		return servletContext;
+	}
+
+	/**
+	 * Store servlet object.
+	 * 
+	 * @param hS
+	 */
+	public static void setServletContext(MasterControlServlet hS) {
+		servletContext = hS;
+	}
+
+	/**
+	 * Get current global configuration object.
+	 * 
+	 * @return
+	 */
+	public static CompositeConfiguration getConfiguration() {
+		if (compositeConfiguration == null) {
+			Configuration.loadConfiguration();
+		}
+		if (compositeConfiguration == null) {
+			log
+					.error("Should never be null here, configuration is failing to load!");
+		}
+		return compositeConfiguration;
+	}
+
+	/**
+	 * Load configuration from both template and override properties files.
+	 */
+	public static void loadConfiguration() {
+		log.trace("Entered loadConfiguration");
+		if (servletContext == null) {
+			log.error("servletContext not set!");
+		}
+		if (compositeConfiguration == null) {
+			log.info("Configuration object not present, instantiating");
+			compositeConfiguration = new CompositeConfiguration();
+
+			PropertiesConfiguration defaults = null;
+			try {
+				defaults = new PropertiesConfiguration(servletContext
+						.getServletContext().getRealPath(DEFAULT_CONFIG));
+				log.info("Loading default configuration from "
+						+ servletContext.getServletContext().getRealPath(
+								DEFAULT_CONFIG));
+			} catch (ConfigurationException e) {
+				log.error("Could not load default configuration from "
+						+ servletContext.getServletContext().getRealPath(
+								DEFAULT_CONFIG));
+				// e.printStackTrace();
+			}
+			if (OVERRIDE_CONFIG != null) {
+				PropertiesConfiguration overrides = null;
+				try {
+					overrides = new PropertiesConfiguration();
+					overrides.setFile(new File(OVERRIDE_CONFIG));
+					overrides
+							.setReloadingStrategy(new FileChangedReloadingStrategy());
+					overrides.load();
+				} catch (ConfigurationException e) {
+					log.info("Could not load overrides", e);
+				}
+				compositeConfiguration.addConfiguration(overrides);
+			}
+			// Afterwards, add defaults so they're read second.
+			compositeConfiguration.addConfiguration(defaults);
+		}
+	}
+
+}
diff --git a/shim-webapp/src/main/java/org/freemedsoftware/shim/Constants.java b/shim-webapp/src/main/java/org/freemedsoftware/shim/Constants.java
new file mode 100644
index 0000000..7baa426
--- /dev/null
+++ b/shim-webapp/src/main/java/org/freemedsoftware/shim/Constants.java
@@ -0,0 +1,29 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.shim;
+
+public class Constants {
+
+}
diff --git a/shim-webapp/src/main/java/org/freemedsoftware/shim/HashMapEntryType.java b/shim-webapp/src/main/java/org/freemedsoftware/shim/HashMapEntryType.java
new file mode 100644
index 0000000..bde7778
--- /dev/null
+++ b/shim-webapp/src/main/java/org/freemedsoftware/shim/HashMapEntryType.java
@@ -0,0 +1,38 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.shim;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlValue;
+
+public class HashMapEntryType {
+
+	@XmlAttribute
+	public String key;
+
+	@XmlValue
+	public String value;
+
+}
diff --git a/shim-webapp/src/main/java/org/freemedsoftware/shim/HashMapType.java b/shim-webapp/src/main/java/org/freemedsoftware/shim/HashMapType.java
new file mode 100644
index 0000000..fc47fc0
--- /dev/null
+++ b/shim-webapp/src/main/java/org/freemedsoftware/shim/HashMapType.java
@@ -0,0 +1,33 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.shim;
+
+import java.util.List;
+
+public class HashMapType {
+
+	public List<HashMapEntryType> entry;
+
+}
diff --git a/shim-webapp/src/main/java/org/freemedsoftware/shim/HashMapXmlAdapter.java b/shim-webapp/src/main/java/org/freemedsoftware/shim/HashMapXmlAdapter.java
new file mode 100644
index 0000000..07706ae
--- /dev/null
+++ b/shim-webapp/src/main/java/org/freemedsoftware/shim/HashMapXmlAdapter.java
@@ -0,0 +1,57 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.shim;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+
+public class HashMapXmlAdapter extends
+		XmlAdapter<HashMapType, HashMap<String, String>> {
+
+	@Override
+	public HashMap<String, String> unmarshal(HashMapType arg0) throws Exception {
+		HashMap<String, String> r = new HashMap<String, String>();
+		for (HashMapEntryType iter : arg0.entry) {
+			r.put(iter.key, iter.value);
+		}
+		return r;
+	}
+
+	@Override
+	public HashMapType marshal(HashMap<String, String> arg0) throws Exception {
+		HashMapType r = new HashMapType();
+		r.entry = new ArrayList<HashMapEntryType>();
+		for (String iter : arg0.keySet()) {
+			HashMapEntryType e = new HashMapEntryType();
+			e.key = iter;
+			e.value = arg0.get(iter);
+			r.entry.add(e);
+		}
+		return r;
+	}
+
+}
diff --git a/shim-webapp/src/main/java/org/freemedsoftware/shim/LoggerServlet.java b/shim-webapp/src/main/java/org/freemedsoftware/shim/LoggerServlet.java
new file mode 100644
index 0000000..750a114
--- /dev/null
+++ b/shim-webapp/src/main/java/org/freemedsoftware/shim/LoggerServlet.java
@@ -0,0 +1,91 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.shim;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.PropertyConfigurator;
+
+/**
+ * Servlet implementation class LoggerServlet
+ */
+public class LoggerServlet extends HttpServlet {
+	private static final long serialVersionUID = 1L;
+
+	static final Logger logger = Logger.getLogger(LoggerServlet.class);
+
+	/**
+	 * Default constructor.
+	 */
+	public LoggerServlet() {
+		System.out.println(getClass().getCanonicalName() + " initializing");
+	}
+
+	@Override
+	public void init() throws ServletException {
+		System.out.println("LogggerServlet init() starting.");
+		String log4jfile = getInitParameter("log4j-properties");
+		System.out.println("log4j-properties: " + log4jfile);
+		if (log4jfile != null) {
+			String propertiesFilename = getServletContext().getRealPath(
+					log4jfile);
+			System.out.println("Using file " + propertiesFilename);
+			PropertyConfigurator.configure(propertiesFilename);
+			logger.info("logger configured.");
+		} else {
+			String propertiesFilename = getServletContext().getRealPath(
+					"/WEB-INF/log4j.properties");
+			System.out.println("Using file " + propertiesFilename);
+			PropertyConfigurator.configure(propertiesFilename);
+			logger.info("logger configured.");
+		}
+		System.out.println("LoggerServlet init() done.");
+	}
+
+	/**
+	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
+	 *      response)
+	 */
+	@Override
+	protected void doGet(HttpServletRequest request,
+			HttpServletResponse response) throws ServletException, IOException {
+	}
+
+	/**
+	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
+	 *      response)
+	 */
+	@Override
+	protected void doPost(HttpServletRequest request,
+			HttpServletResponse response) throws ServletException, IOException {
+	}
+
+}
diff --git a/shim-webapp/src/main/java/org/freemedsoftware/shim/MasterControlServlet.java b/shim-webapp/src/main/java/org/freemedsoftware/shim/MasterControlServlet.java
new file mode 100644
index 0000000..0472627
--- /dev/null
+++ b/shim-webapp/src/main/java/org/freemedsoftware/shim/MasterControlServlet.java
@@ -0,0 +1,328 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.shim;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+
+import org.apache.commons.configuration.CompositeConfiguration;
+import org.apache.log4j.Logger;
+import org.freemedsoftware.device.DosingPumpInterface;
+import org.freemedsoftware.device.JobStoreItem;
+import org.freemedsoftware.device.LabelPrinterInterface;
+import org.freemedsoftware.device.PersistentJobStoreDAO;
+import org.freemedsoftware.device.ShimDeviceManager;
+import org.freemedsoftware.device.SignatureInterface;
+import org.tmatesoft.sqljet.core.SqlJetException;
+
+public class MasterControlServlet extends HttpServlet {
+
+	private static final long serialVersionUID = 672124984404116767L;
+
+	static final Logger logger = Logger.getLogger(MasterControlServlet.class);
+
+	protected final int THREAD_SLEEP_TIME = 250;
+
+	protected CompositeConfiguration config = null;
+
+	protected static ShimDeviceManager<DosingPumpInterface> dosingPumpDeviceManager = null;
+
+	protected static ShimDeviceManager<SignatureInterface> signatureDeviceManager = null;
+
+	protected static ShimDeviceManager<LabelPrinterInterface> labelPrinterDeviceManager = null;
+
+	protected Timer timer = new Timer();
+
+	public void init() throws ServletException {
+		logger.info("MasterControlServlet initializing");
+
+		logger.info("Loading configuration");
+		Configuration.setServletContext(this);
+		Configuration.loadConfiguration();
+
+		config = Configuration.getConfiguration();
+
+		String jobstoreLocation = config.getString("jobstore.location");
+
+		logger.info("Initializing connection to persistent job store : "
+				+ jobstoreLocation);
+		if (new File(jobstoreLocation).exists()) {
+			logger.info("Found existing job store, no need to initialize");
+			try {
+				PersistentJobStoreDAO.open(jobstoreLocation);
+			} catch (SqlJetException e) {
+				throw new ServletException(
+						"Unable to open persistent job store");
+			}
+		} else {
+			logger.info("Attempting to create new job store at "
+					+ jobstoreLocation);
+			try {
+				PersistentJobStoreDAO.create(jobstoreLocation);
+			} catch (SqlJetException ex) {
+				throw new ServletException(
+						"Unable to open persistent job store");
+			}
+		}
+
+		launchWorkerThreads();
+
+		logger.info("MasterControlServlet init finished");
+	}
+
+	@SuppressWarnings("unchecked")
+	public void launchWorkerThreads() {
+		logger.info("Launching worker threads");
+
+		HashMap<String, Object> driverConfig = new HashMap<String, Object>();
+		Iterator<String> configKeys = config.getKeys();
+		while (configKeys.hasNext()) {
+			String k = configKeys.next();
+			driverConfig.put(k, config.getString(k));
+		}
+
+		// Initialize signature pad if driver is defined
+
+		String signatureDriver = config.getString("driver.signature");
+		if (signatureDriver != null) {
+			logger.info("Initializing signature pad driver " + signatureDriver);
+			try {
+				logger.debug("instantiating driver");
+				signatureDeviceManager = new ShimDeviceManager<SignatureInterface>(
+						signatureDriver);
+				signatureDeviceManager.getDeviceInstance().configure(
+						driverConfig);
+				logger.debug("running init() for driver");
+				if (signatureDeviceManager == null) {
+					logger.error("Signature manager is null!!");
+				}
+				signatureDeviceManager.init();
+			} catch (Exception e) {
+				logger.error(e);
+			}
+		} else {
+			logger.warn("No signature pad driver specified, skipping.");
+		}
+
+		// Initialize signature pad if driver is defined
+
+		String dosingPumpDriver = config.getString("driver.dosingpump");
+		if (dosingPumpDriver != null) {
+			logger.info("Initializing dosing pump driver " + dosingPumpDriver);
+			try {
+				logger.debug("instantiating driver");
+				dosingPumpDeviceManager = new ShimDeviceManager<DosingPumpInterface>(
+						dosingPumpDriver);
+				dosingPumpDeviceManager.getDeviceInstance().configure(
+						driverConfig);
+				logger.debug("running init() for driver");
+				if (dosingPumpDeviceManager == null) {
+					logger.error("Dosing pump manager is null!!");
+				}
+				dosingPumpDeviceManager.init();
+			} catch (Exception e) {
+				logger.error(e);
+			}
+		} else {
+			logger.warn("No dosing pump driver specified, skipping.");
+		}
+
+		// Initialize label printer, if a driver is defined
+
+		String labelPrinterDriver = config.getString("driver.labelprinter");
+		if (labelPrinterDriver != null) {
+			logger.info("Initializing label printer driver "
+					+ labelPrinterDriver);
+			try {
+				logger.debug("instantiating driver");
+				labelPrinterDeviceManager = new ShimDeviceManager<LabelPrinterInterface>(
+						labelPrinterDriver);
+				labelPrinterDeviceManager.getDeviceInstance().configure(
+						driverConfig);
+				logger.debug("running init() for driver");
+				if (labelPrinterDeviceManager == null) {
+					logger.error("Label printer manager is null!!");
+				}
+				labelPrinterDeviceManager.init();
+			} catch (Exception e) {
+				logger.error(e);
+			}
+		} else {
+			logger.warn("No signature pad driver specified, skipping.");
+		}
+
+		logger.info("Launching job store scheduler timer");
+		timer = new Timer();
+		timer.schedule(new TimerTask() {
+
+			@Override
+			public void run() {
+				while (!Thread.interrupted()) {
+					try {
+						Thread.sleep(THREAD_SLEEP_TIME);
+						scanForJobs();
+					} catch (InterruptedException e) {
+						logger.warn(e);
+					}
+				}
+			}
+
+			protected void scanForJobs() {
+				JobStoreItem labelItem = null;
+				JobStoreItem signatureItem = null;
+				JobStoreItem vitalsItem = null;
+				try {
+					List<JobStoreItem> items = PersistentJobStoreDAO
+							.unassignedJobs();
+					Iterator<JobStoreItem> iter = items.iterator();
+					while (iter.hasNext() && signatureItem == null
+							&& vitalsItem == null && labelItem == null) {
+						JobStoreItem thisItem = iter.next();
+						if (thisItem.getDevice().equalsIgnoreCase(
+								JobStoreItem.DEVICE_SIGNATURE)
+								&& signatureItem == null) {
+							signatureItem = thisItem;
+						}
+						if (thisItem.getDevice().equalsIgnoreCase(
+								JobStoreItem.DEVICE_LABEL)
+								&& labelItem == null) {
+							labelItem = thisItem;
+						}
+						if (thisItem.getDevice().equalsIgnoreCase(
+								JobStoreItem.DEVICE_VITALS)
+								&& signatureItem == null) {
+							vitalsItem = thisItem;
+						}
+					}
+				} catch (SqlJetException e) {
+					logger.error(e);
+				}
+
+				// Process any new signature requests
+
+				if (signatureItem != null && signatureDeviceManager != null) {
+					logger.info("Found signature item to be processed (id = "
+							+ signatureItem.getId() + ")");
+					if (!signatureDeviceManager.getDeviceInstance()
+							.isProcessing()) {
+						try {
+							signatureDeviceManager.getDeviceInstance()
+									.initJobRequest(signatureItem);
+
+							// Update with pending status
+							signatureItem
+									.setStatus(JobStoreItem.STATUS_PENDING);
+							PersistentJobStoreDAO.update(signatureItem);
+						} catch (Exception e) {
+							logger.error(e);
+						}
+					} else {
+						logger
+								.warn("Device is processing, skipping new job load");
+					}
+				}
+
+				// Process any new label requests
+
+				if (labelItem != null && labelPrinterDeviceManager != null) {
+					logger.info("Found label item to be processed (id = "
+							+ labelItem.getId() + ")");
+					if (!labelPrinterDeviceManager.getDeviceInstance()
+							.isProcessing()) {
+						try {
+							labelPrinterDeviceManager.getDeviceInstance()
+									.initJobRequest(labelItem);
+
+							// Update with pending status
+							labelItem.setStatus(JobStoreItem.STATUS_PENDING);
+							PersistentJobStoreDAO.update(labelItem);
+						} catch (Exception e) {
+							logger.error(e);
+						}
+					} else {
+						logger
+								.warn("Device is processing, skipping new job load");
+					}
+				}
+
+			}
+
+		}, THREAD_SLEEP_TIME, THREAD_SLEEP_TIME);
+	}
+
+	public static ShimDeviceManager<DosingPumpInterface> getDosingPumpDeviceManager() {
+		return dosingPumpDeviceManager;
+	}
+
+	public static ShimDeviceManager<SignatureInterface> getSignatureDeviceManager() {
+		return signatureDeviceManager;
+	}
+
+	public static ShimDeviceManager<LabelPrinterInterface> getLabelPrinterDeviceManager() {
+		return labelPrinterDeviceManager;
+	}
+
+	@Override
+	public void destroy() {
+		if (signatureDeviceManager != null) {
+			logger.info("Closing signature manager");
+			try {
+				signatureDeviceManager.close();
+			} catch (Exception e) {
+				logger.warn(e);
+			}
+		}
+		if (labelPrinterDeviceManager != null) {
+			logger.info("Closing label printer manager");
+			try {
+				labelPrinterDeviceManager.close();
+			} catch (Exception e) {
+				logger.warn(e);
+			}
+		}
+		if (dosingPumpDeviceManager != null) {
+			logger.info("Closing dosing pump manager");
+			try {
+				dosingPumpDeviceManager.close();
+			} catch (Exception e) {
+				logger.warn(e);
+			}
+		}
+		if (timer != null) {
+			logger.info("Cancelling timer instance");
+			timer.cancel();
+		}
+		PersistentJobStoreDAO.close();
+		super.destroy();
+	}
+
+}
diff --git a/shim-webapp/src/main/java/org/freemedsoftware/shim/ShimDeviceInformation.java b/shim-webapp/src/main/java/org/freemedsoftware/shim/ShimDeviceInformation.java
new file mode 100644
index 0000000..ef953dc
--- /dev/null
+++ b/shim-webapp/src/main/java/org/freemedsoftware/shim/ShimDeviceInformation.java
@@ -0,0 +1,65 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.shim;
+
+import java.io.Serializable;
+
+import org.freemedsoftware.device.DeviceCapability;
+
+public class ShimDeviceInformation implements Serializable {
+
+	private static final long serialVersionUID = 7325861056406660405L;
+
+	private String deviceName;
+
+	private String deviceDriver;
+
+	private DeviceCapability deviceType;
+
+	public void setDeviceName(String deviceName) {
+		this.deviceName = deviceName;
+	}
+
+	public String getDeviceName() {
+		return deviceName;
+	}
+
+	public void setDeviceDriver(String deviceDriver) {
+		this.deviceDriver = deviceDriver;
+	}
+
+	public String getDeviceDriver() {
+		return deviceDriver;
+	}
+
+	public void setDeviceType(DeviceCapability deviceType) {
+		this.deviceType = deviceType;
+	}
+
+	public DeviceCapability getDeviceType() {
+		return deviceType;
+	}
+
+}
diff --git a/shim-webapp/src/main/java/org/freemedsoftware/shim/ShimService.java b/shim-webapp/src/main/java/org/freemedsoftware/shim/ShimService.java
new file mode 100644
index 0000000..809b77e
--- /dev/null
+++ b/shim-webapp/src/main/java/org/freemedsoftware/shim/ShimService.java
@@ -0,0 +1,76 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.shim;
+
+import java.util.HashMap;
+import java.util.List;
+
+import javax.jws.WebParam;
+import javax.jws.WebService;
+import javax.ws.rs.PathParam;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+import org.freemedsoftware.device.DosingPumpCommand;
+import org.freemedsoftware.device.JobStoreItem;
+import org.freemedsoftware.shim.exception.DeviceNotAvailableException;
+
+ at WebService
+public interface ShimService {
+
+	public static int PROTOCOL_VERSION = 2;
+
+	public Integer getProtocolVersion();
+
+	public Integer requestLabel(
+			@PathParam("printTemplate") @WebParam(name = "printTemplate") String printTemplate,
+			@PathParam("printParameters") @WebParam(name = "printParameters") @XmlJavaTypeAdapter(HashMapXmlAdapter.class) HashMap<String, String> printParameters,
+			@PathParam("copyCount") @WebParam(name = "copyCount") Integer copyCount)
+			throws DeviceNotAvailableException;
+
+	public Integer requestSignature(
+			@PathParam("displayInformation") @WebParam(name = "displayInformation") String displayInformation)
+			throws DeviceNotAvailableException;
+
+	public SignatureStatus getJobStatus(
+			@PathParam("requestId") @WebParam(name = "requestId") Integer requestId)
+			throws Exception;
+
+	public JobStoreItem getJobItem(
+			@PathParam("requestId") @WebParam(name = "requestId") Integer requestId)
+			throws Exception;
+
+	public String requestDosingAction(
+			@PathParam("command") @WebParam(name = "command") DosingPumpCommand command,
+			@PathParam("param") @WebParam(name = "param") String param)
+			throws Exception;
+
+	/*
+	 * public @XmlJavaTypeAdapter(HashMapXmlAdapter.class) HashMap<String,
+	 * String> getTestMap();
+	 */
+
+	public List<ShimDeviceInformation> getDevices();
+
+}
diff --git a/shim-webapp/src/main/java/org/freemedsoftware/shim/ShimServiceImpl.java b/shim-webapp/src/main/java/org/freemedsoftware/shim/ShimServiceImpl.java
new file mode 100644
index 0000000..704853d
--- /dev/null
+++ b/shim-webapp/src/main/java/org/freemedsoftware/shim/ShimServiceImpl.java
@@ -0,0 +1,187 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.shim;
+
+import java.util.HashMap;
+import java.util.List;
+
+import javax.annotation.Resource;
+import javax.jws.WebService;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.xml.ws.WebServiceContext;
+
+import org.apache.log4j.Logger;
+import org.freemedsoftware.device.DosingPumpCommand;
+import org.freemedsoftware.device.DosingPumpInterface;
+import org.freemedsoftware.device.JobStoreItem;
+import org.freemedsoftware.device.LabelPrinterInterface;
+import org.freemedsoftware.device.PersistentJobStoreDAO;
+import org.freemedsoftware.device.ShimDeviceManager;
+import org.freemedsoftware.device.SignatureInterface;
+import org.freemedsoftware.shim.exception.DeviceNotAvailableException;
+import org.tmatesoft.sqljet.core.SqlJetException;
+
+ at WebService(endpointInterface = "org.freemedsoftware.shim.ShimService", serviceName = "Shim")
+public class ShimServiceImpl implements ShimService {
+
+	@Resource
+	WebServiceContext context;
+
+	static final Logger log = Logger.getLogger(ShimServiceImpl.class);
+
+	@GET
+	@Path("protocolversion")
+	@Produces("application/json")
+	@Override
+	public Integer getProtocolVersion() {
+		return PROTOCOL_VERSION;
+	}
+
+	@GET
+	@Path("label/{printTemplate}/{printParameters}/{copyCount}")
+	@Produces("application/json")
+	@Override
+	public Integer requestLabel(String printTemplate,
+			HashMap<String, String> printParameters, Integer copyCount)
+			throws DeviceNotAvailableException {
+		ShimDeviceManager<LabelPrinterInterface> manager = MasterControlServlet
+				.getLabelPrinterDeviceManager();
+		if (manager == null) {
+			throw new DeviceNotAvailableException();
+		}
+		JobStoreItem item = new JobStoreItem();
+		Integer itemId = 0;
+		item.setStatus(JobStoreItem.STATUS_NEW);
+		item.setDevice(JobStoreItem.DEVICE_LABEL);
+		item.setPrintTemplate(printTemplate);
+		item.setPrintParameters(printParameters);
+		try {
+			itemId = PersistentJobStoreDAO.insert(item);
+		} catch (SqlJetException e) {
+			log.error(e);
+			throw new DeviceNotAvailableException();
+		}
+		return itemId;
+	}
+
+	@GET
+	@Path("signature/{displayInformation}")
+	@Produces("application/json")
+	@Override
+	public Integer requestSignature(String displayInformation)
+			throws DeviceNotAvailableException {
+		ShimDeviceManager<SignatureInterface> manager = MasterControlServlet
+				.getSignatureDeviceManager();
+		if (manager == null) {
+			throw new DeviceNotAvailableException();
+		}
+		JobStoreItem item = new JobStoreItem();
+		Integer itemId = 0;
+		item.setStatus(JobStoreItem.STATUS_NEW);
+		item.setDevice(JobStoreItem.DEVICE_SIGNATURE);
+		item.setDisplayText(displayInformation);
+		try {
+			itemId = PersistentJobStoreDAO.insert(item);
+		} catch (SqlJetException e) {
+			log.error(e);
+			throw new DeviceNotAvailableException();
+		}
+		return itemId;
+	}
+
+	@GET
+	@Path("dosing/{command}/{param}")
+	@Produces("application/json")
+	@Override
+	public String requestDosingAction(DosingPumpCommand command, String param)
+			throws Exception {
+		ShimDeviceManager<DosingPumpInterface> manager = MasterControlServlet
+				.getDosingPumpDeviceManager();
+		if (manager == null) {
+			throw new DeviceNotAvailableException();
+		}
+		if (command == DosingPumpCommand.DISPENSE) {
+			return manager.getDeviceInstance().dispenseDose(
+					Integer.parseInt(param));
+		}
+		if (command == DosingPumpCommand.GET_STATUS) {
+			return manager.getDeviceInstance().getPumpStatus();
+		}
+		if (command == DosingPumpCommand.PRIME) {
+			return manager.getDeviceInstance().primePump();
+		}
+		if (command == DosingPumpCommand.REVERSE) {
+			return manager.getDeviceInstance().reversePump();
+		}
+
+		if (command != null) {
+			throw new Exception("Invalid command given!");
+		} else {
+			return "NULL";
+		}
+	}
+
+	@GET
+	@Path("jobstatus/{requestId}")
+	@Produces("application/json")
+	@Override
+	public SignatureStatus getJobStatus(Integer requestId) throws Exception {
+		JobStoreItem item = PersistentJobStoreDAO.get(requestId);
+		return SignatureStatus.fromString(item.getStatus());
+	}
+
+	@GET
+	@Path("jobitem/{requestId}")
+	@Produces("application/json")
+	@Override
+	public JobStoreItem getJobItem(Integer requestId) throws Exception {
+		JobStoreItem item = PersistentJobStoreDAO.get(requestId);
+		return item;
+	}
+
+	@GET
+	@Path("devices")
+	@Produces("application/json")
+	@Override
+	public List<ShimDeviceInformation> getDevices() {
+		return null;
+	}
+
+	/*
+	 * @GET
+	 * 
+	 * @Path("testmap")
+	 * 
+	 * @Produces("application/json")
+	 * 
+	 * @Override public HashMap<String, String> getTestMap() { HashMap<String,
+	 * String> test = new HashMap<String, String>(); test.put("key_a",
+	 * "value_a"); test.put("key_b", "value_b"); test.put("key_c", "value_c");
+	 * return test; }
+	 */
+
+}
\ No newline at end of file
diff --git a/shim-webapp/src/main/java/org/freemedsoftware/shim/SignatureStatus.java b/shim-webapp/src/main/java/org/freemedsoftware/shim/SignatureStatus.java
new file mode 100644
index 0000000..c68edd5
--- /dev/null
+++ b/shim-webapp/src/main/java/org/freemedsoftware/shim/SignatureStatus.java
@@ -0,0 +1,54 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.shim;
+
+public enum SignatureStatus {
+	PENDING("PENDING"), COMPLETE("COMPLETE"), ERROR("ERROR"), NEW("NEW");
+
+	private String textual = null;
+
+	SignatureStatus(String textual) {
+		this.textual = textual;
+	}
+
+	public static SignatureStatus fromString(String textual) {
+		if (textual.equalsIgnoreCase("PENDING")) {
+			return SignatureStatus.PENDING;
+		} else if (textual.equalsIgnoreCase("COMPLETE")) {
+			return SignatureStatus.COMPLETE;
+		} else if (textual.equalsIgnoreCase("ERROR")) {
+			return SignatureStatus.ERROR;
+		} else if (textual.equalsIgnoreCase("NEW")) {
+			return SignatureStatus.NEW;
+		} else {
+			return null;
+		}
+	}
+
+	@Override
+	public String toString() {
+		return this.textual;
+	}
+}
diff --git a/shim-webapp/src/main/java/org/freemedsoftware/shim/exception/DeviceNotAvailableException.java b/shim-webapp/src/main/java/org/freemedsoftware/shim/exception/DeviceNotAvailableException.java
new file mode 100644
index 0000000..e9baab6
--- /dev/null
+++ b/shim-webapp/src/main/java/org/freemedsoftware/shim/exception/DeviceNotAvailableException.java
@@ -0,0 +1,31 @@
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+package org.freemedsoftware.shim.exception;
+
+public class DeviceNotAvailableException extends Exception {
+
+	private static final long serialVersionUID = 1312394315315408746L;
+
+}
diff --git a/shim-webapp/src/main/webapp/WEB-INF/cxf-servlet.xml b/shim-webapp/src/main/webapp/WEB-INF/cxf-servlet.xml
new file mode 100644
index 0000000..6210c5a
--- /dev/null
+++ b/shim-webapp/src/main/webapp/WEB-INF/cxf-servlet.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
+	xmlns:jaxrs="http://cxf.apache.org/jaxrs"
+	xsi:schemaLocation="
+http://www.springframework.org/schema/beans
+http://www.springframework.org/schema/beans/spring-beans.xsd
+http://cxf.apache.org/jaxrs
+http://cxf.apache.org/schemas/jaxrs.xsd
+http://cxf.apache.org/jaxws
+http://cxf.apache.org/schemas/jaxws.xsd">
+
+	<import resource="classpath:META-INF/cxf/cxf.xml" />
+	<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
+
+	<jaxws:endpoint id="Shim"
+		implementor="org.freemedsoftware.shim.ShimServiceImpl" address="/Shim" />
+
+</beans>
diff --git a/shim-webapp/src/main/webapp/WEB-INF/cxf.xml b/shim-webapp/src/main/webapp/WEB-INF/cxf.xml
new file mode 100644
index 0000000..856662a
--- /dev/null
+++ b/shim-webapp/src/main/webapp/WEB-INF/cxf.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+	<!-- $Id$ -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cxf="http://cxf.apache.org/core"
+	xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
+	xsi:schemaLocation="
+       http://www.springframework.org/schema/beans
+       http://www.springframework.org/schema/beans/spring-beans.xsd
+       http://cxf.apache.org/core
+       http://cxf.apache.org/schemas/core.xsd
+       http://cxf.apache.org/jaxws
+       http://cxf.apache.org/schemas/jaxws.xsd
+       http://cxf.apache.org/jaxrs
+       http://cxf.apache.org/schemas/jaxrs.xsd"
+	default-autowire="byName">
+
+	<import resource="classpath:META-INF/cxf/cxf.xml" />
+	<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
+
+	<cxf:bus>
+		<cxf:features>
+			<cxf:logging />
+		</cxf:features>
+	</cxf:bus>
+
+	<!-- Service bean -->
+	<bean id="service" class="org.freemedsoftware.shim.ShimServiceImpl"
+		autowire="byName" />
+
+	<!-- REST service definition -->
+	<jaxrs:server id="restServer" address="/rest/">
+		<jaxrs:serviceBeans>
+			<ref bean="service" />
+		</jaxrs:serviceBeans>
+		<jaxrs:extensionMappings>
+			<entry key="feed" value="application/atom+xml" />
+			<entry key="json" value="application/json" />
+			<entry key="xml" value="application/xml" />
+			<entry key="html" value="text/html" />
+		</jaxrs:extensionMappings>
+	</jaxrs:server>
+
+	<!-- SOAP service definition -->
+	<bean id="jaxbBean" class="org.apache.cxf.jaxb.JAXBDataBinding"
+		scope="prototype" />
+
+	<bean id="jaxws-and-aegis-service-factory" class="org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean"
+		scope="prototype">
+		<property name="dataBinding" ref="jaxbBean" />
+		<property name="serviceConfigurations">
+			<list>
+				<bean class="org.apache.cxf.jaxws.support.JaxWsServiceConfiguration" />
+				<bean class="org.apache.cxf.aegis.databinding.AegisServiceConfiguration" />
+				<bean class="org.apache.cxf.service.factory.DefaultServiceConfiguration" />
+			</list>
+		</property>
+	</bean>
+
+	<jaxws:endpoint id="serviceEndpoint"
+		implementor="org.freemedsoftware.shim.ShimServiceImpl" address="/ShimService">
+		<jaxws:serviceFactory>
+			<ref bean="jaxws-and-aegis-service-factory" />
+		</jaxws:serviceFactory>
+	</jaxws:endpoint>
+
+</beans>
diff --git a/shim-webapp/src/main/webapp/WEB-INF/log4j.properties b/shim-webapp/src/main/webapp/WEB-INF/log4j.properties
new file mode 100644
index 0000000..36c2d21
--- /dev/null
+++ b/shim-webapp/src/main/webapp/WEB-INF/log4j.properties
@@ -0,0 +1,35 @@
+#
+# $Id$
+# jeff at freemedsoftware.org
+#
+
+log4j.rootLogger=DEBUG, AppLogAppender
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
+
+log4j.appender.AppLogAppender=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.AppLogAppender.File=${catalina.home}/logs/shim.log
+log4j.appender.AppLogAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.AppLogAppender.layout.ConversionPattern=%d %-5p %c %x - %m%n
+log4j.appender.AppLogAppender.DatePattern='.'yyyy-MM-dd
+
+log4j.appender.DeviceLogAppender=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.DeviceLogAppender.File=${catalina.home}/logs/device.log
+log4j.appender.DeviceLogAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.DeviceLogAppender.layout.ConversionPattern=%d %-5p %c %x - %m%n
+log4j.appender.DeviceLogAppender.DatePattern='.'yyyy-MM-dd
+
+log4j.appender.ServiceLogAppender=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.ServiceLogAppender.File=${catalina.home}/logs/service.log
+log4j.appender.ServiceLogAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.ServiceLogAppender.layout.ConversionPattern=%d %-5p %c %x - %m%n
+log4j.appender.ServiceLogAppender.DatePattern='.'yyyy-MM-dd
+
+# Define special class appenders here
+log4j.logger.org.apache.catalina=WARN, AppLogAppender
+log4j.logger.org.freemedsoftware.shim.ShimService=DEBUG, ServiceLogAppender
+log4j.logger.org.freemedsoftware.shim.ShimServiceImpl=DEBUG, ServiceLogAppender
+log4j.logger.org.freemedsoftware.device=DEBUG, DeviceLogAppender
+
diff --git a/shim-webapp/src/main/webapp/WEB-INF/shim-default.properties b/shim-webapp/src/main/webapp/WEB-INF/shim-default.properties
new file mode 100644
index 0000000..6da930c
--- /dev/null
+++ b/shim-webapp/src/main/webapp/WEB-INF/shim-default.properties
@@ -0,0 +1,57 @@
+;
+; $Id$
+;
+; Authors:
+;      Jeff Buchbinder <jeff at freemedsoftware.org>
+;
+; FreeMED Electronic Medical Record / Practice Management System
+; Copyright (C) 1999-2012 FreeMED Software Foundation
+;
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+
+; Persistent Job Store location
+
+jobstore.location=./work/jobstore.db
+
+; Default drivers
+
+driver.dosingpump=org.freemedsoftware.device.impl.DosingPumpScilogShim
+driver.labelprinter=org.freemedsoftware.device.impl.LabelEscPosShim
+driver.signature=org.freemedsoftware.device.impl.SignatureTopazShim
+
+; Label Printer defaults
+
+org.freemedsoftware.device.impl.LabelEscPosShim.port=/dev/lp0
+org.freemedsoftware.device.impl.LabelEscPosShim.timeout=30
+
+; TOPAZ Signature Tablet defaults
+
+org.freemedsoftware.device.impl.SignatureTopazShim.tabletModel=SignatureGemLCD1X5
+org.freemedsoftware.device.impl.SignatureTopazShim.tabletPort=HID1
+
+; Scilog Dosing Pump defaults
+org.freemedsoftware.device.impl.DosingPumpScilogShim.enabled=false
+org.freemedsoftware.device.impl.DosingPumpScilogShim.port=/dev/ttyS0
+org.freemedsoftware.device.impl.DosingPumpScilogShim.baud=9600
+org.freemedsoftware.device.impl.DosingPumpScilogShim.timeout=100
+org.freemedsoftware.device.impl.DosingPumpScilogShim.reversePumpDuration=30
+org.freemedsoftware.device.impl.DosingPumpScilogShim.primePumpDuration=90
+
+; Microlab 3500 defaults
+org.freemedsoftware.device.impl.LabMicroLab3500Shim.enabled=false
+org.freemedsoftware.device.impl.LabMicroLab3500Shim.port=/dev/ttyS0
+org.freemedsoftware.device.impl.LabMicroLab3500Shim.baud=4800
+org.freemedsoftware.device.impl.LabMicroLab3500Shim.timeout=100
+
diff --git a/shim-webapp/src/main/webapp/WEB-INF/web.xml b/shim-webapp/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..7c9c295
--- /dev/null
+++ b/shim-webapp/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+	<!--
+		$Id$
+	-->
+<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+	id="WebApp_ID" version="2.5">
+	<display-name>shim</display-name>
+	<welcome-file-list>
+		<welcome-file>index.html</welcome-file>
+		<welcome-file>index.htm</welcome-file>
+		<welcome-file>index.jsp</welcome-file>
+		<welcome-file>default.html</welcome-file>
+		<welcome-file>default.htm</welcome-file>
+		<welcome-file>default.jsp</welcome-file>
+	</welcome-file-list>
+
+	<!-- Logging -->
+
+	<servlet>
+		<description></description>
+		<display-name>LoggerServlet</display-name>
+		<servlet-name>LoggerServlet</servlet-name>
+		<servlet-class>org.freemedsoftware.shim.LoggerServlet</servlet-class>
+		<load-on-startup>1</load-on-startup>
+	</servlet>
+	<servlet-mapping>
+		<servlet-name>LoggerServlet</servlet-name>
+		<url-pattern>/LoggerServlet</url-pattern>
+	</servlet-mapping>
+	<context-param>
+		<param-name>log4jConfigLocation</param-name>
+		<param-value>/WEB-INF/log4j.properties</param-value>
+	</context-param>
+
+	<!-- Control servlet -->
+
+	<servlet>
+		<description>Servlet to handle init/shutdown operations</description>
+		<display-name>MasterControl</display-name>
+		<servlet-name>MasterControl</servlet-name>
+		<servlet-class>org.freemedsoftware.shim.MasterControlServlet</servlet-class>
+		<load-on-startup>1</load-on-startup>
+	</servlet>
+	<servlet-mapping>
+		<servlet-name>MasterControl</servlet-name>
+		<url-pattern>/MasterControl</url-pattern>
+	</servlet-mapping>
+
+	<!-- Web services -->
+
+	<display-name>Auth Manager</display-name>
+	<context-param>
+		<param-name>contextConfigLocation</param-name>
+		<param-value>/WEB-INF/cxf.xml</param-value>
+	</context-param>
+
+	<listener>
+		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+	</listener>
+	<servlet>
+		<servlet-name>CXFServlet</servlet-name>
+		<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
+	</servlet>
+	<servlet-mapping>
+		<servlet-name>CXFServlet</servlet-name>
+		<url-pattern>/services/*</url-pattern>
+	</servlet-mapping>
+
+
+	<!-- Define security constraints -->
+
+	<security-constraint>
+		<web-resource-collection>
+			<web-resource-name>default</web-resource-name>
+			<url-pattern>/services/*</url-pattern>
+			<http-method>GET</http-method>
+			<http-method>POST</http-method>
+		</web-resource-collection>
+		<auth-constraint>
+			<role-name>default</role-name>
+		</auth-constraint>
+	</security-constraint>
+	<security-constraint>
+		<web-resource-collection>
+			<web-resource-name>default</web-resource-name>
+			<url-pattern>/admin/*</url-pattern>
+			<http-method>GET</http-method>
+			<http-method>POST</http-method>
+		</web-resource-collection>
+		<auth-constraint>
+			<role-name>default</role-name>
+		</auth-constraint>
+	</security-constraint>
+	<security-role>
+		<description>Default security role</description>
+		<role-name>default</role-name>
+	</security-role>
+
+	<login-config>
+		<auth-method>BASIC</auth-method>
+		<realm-name>default</realm-name>
+	</login-config>
+
+</web-app>
diff --git a/shim-webapp/src/main/webapp/admin/control.jsp b/shim-webapp/src/main/webapp/admin/control.jsp
new file mode 100644
index 0000000..846140b
--- /dev/null
+++ b/shim-webapp/src/main/webapp/admin/control.jsp
@@ -0,0 +1,88 @@
+<%-- 
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ --%>
+<html>
+<head>
+<title>FreeSHIM</title>
+<meta http-equiv="refresh" content="5;url=status.jsp">
+</head>
+<body>
+
+<!-- Header -->
+
+<table border="0" cellpadding="5" width="100%">
+	<tr>
+		<td align="right"><img src="../img/freeshim.png" border="0" alt="" width="200" height="98" /></td>
+		<td align="left">FreeSHIM</td>
+	</tr>
+</table>
+
+<%@ page import="java.util.*"%>
+<%@ page import="org.freemedsoftware.shim.Configuration"%>
+<%@ page import="org.freemedsoftware.shim.MasterControlServlet"%>
+<%
+	MasterControlServlet s = Configuration.getServletContext();
+	if (request.getParameter("device").equals("DOSING_PUMP")) {
+		if (s.getDosingPumpDeviceManager().getActive()) {
+			// Stop
+			out.println("<b>Stopping DOSING_PUMP device</b><br/>");
+			s.getDosingPumpDeviceManager().close();
+			out.println("<b>Stopped DOSING_PUMP device</b><br/>");			
+		} else {
+			// Start
+			out.println("<b>Starting DOSING_PUMP device</b><br/>");
+			s.getDosingPumpDeviceManager().init();
+			out.println("<b>Started DOSING_PUMP device</b><br/>");
+		}
+	} else if (request.getParameter("device").equals("SIGNATURE")) {
+		if (s.getSignatureDeviceManager().getActive()) {
+			// Stop
+			out.println("<b>Stopping LABEL device</b><br/>");
+			s.getSignatureDeviceManager().close();
+			out.println("<b>Stopped LABEL device</b><br/>");			
+		} else {
+			// Start
+			out.println("<b>Starting LABEL device</b><br/>");
+			s.getSignatureDeviceManager().init();
+			out.println("<b>Started LABEL device</b><br/>");
+		}
+	} else if (request.getParameter("device").equals("LABEL")) {
+		if (s.getLabelPrinterDeviceManager().getActive()) {
+			// Stop
+			out.println("<b>Stopping LABEL device</b><br/>");
+			s.getLabelPrinterDeviceManager().close();
+			out.println("<b>Stopped LABEL device</b><br/>");			
+		} else {
+			// Start
+			out.println("<b>Starting LABEL device</b><br/>");
+			s.getLabelPrinterDeviceManager().init();
+			out.println("<b>Started LABEL device</b><br/>");
+		}
+	} else {
+		out.println("Invalid device specified.<br/>");
+	}	
+	out.println("Please wait to return to the status page.<br/>");
+%>
+
+</body>
+</html>
diff --git a/shim-webapp/src/main/webapp/admin/index.jsp b/shim-webapp/src/main/webapp/admin/index.jsp
new file mode 100644
index 0000000..f2e179f
--- /dev/null
+++ b/shim-webapp/src/main/webapp/admin/index.jsp
@@ -0,0 +1,44 @@
+<%-- 
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ --%>
+<html>
+<head>
+<title>FreeSHIM</title>
+</head>
+<body>
+
+<!-- Header -->
+
+<table border="0" cellpadding="5" width="100%">
+	<tr>
+		<td align="right"><img src="../img/freeshim.png" border="0" alt="" width="200" height="98" /></td>
+		<td align="left">FreeSHIM</td>
+	</tr>
+</table>
+
+<ul>
+	<li><a href="status.jsp">Status</a> - Manager drivers</li>
+</ul>
+
+</body>
+</html>
diff --git a/shim-webapp/src/main/webapp/admin/status.jsp b/shim-webapp/src/main/webapp/admin/status.jsp
new file mode 100644
index 0000000..6df72e0
--- /dev/null
+++ b/shim-webapp/src/main/webapp/admin/status.jsp
@@ -0,0 +1,101 @@
+<%-- 
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ --%>
+<html>
+<head>
+<title>FreeSHIM</title>
+</head>
+<body>
+
+<!-- Header -->
+
+<table border="0" cellpadding="5" width="100%">
+	<tr>
+		<td align="right"><img src="../img/freeshim.png" border="0" alt="" width="200" height="98" /></td>
+		<td align="left">FreeSHIM</td>
+	</tr>
+</table>
+
+<%@ page import="java.util.*"%>
+<%@ page import="org.freemedsoftware.device.*"%>
+<%@ page import="org.freemedsoftware.shim.*"%>
+<%
+	MasterControlServlet s = Configuration.getServletContext();
+	ShimDeviceManager<DosingPumpInterface> dosingPumpDeviceManager = s.getDosingPumpDeviceManager();
+	ShimDeviceManager<SignatureInterface> signatureDeviceManager = s.getSignatureDeviceManager();
+	ShimDeviceManager<LabelPrinterInterface> labelPrinterDeviceManager = s.getLabelPrinterDeviceManager();
+%>
+
+<table border="1" cellpadding="5">
+	<tr>
+		<th>Device</th>
+		<th>Driver</th>
+		<th>Active</th>
+		<th>Action</th>
+	</tr>
+	<tr>
+		<th>DOSING_PUMP</th>
+		<% if (dosingPumpDeviceManager == null) { %>
+		<td>NO DRIVER LOADED</td>
+		<td>false</td>
+		<% } else { %>
+		<td><%= dosingPumpDeviceManager.getClassName() %></td>
+		<td><%= dosingPumpDeviceManager.getActive() %></td>
+		<% } %>
+		<td><form method="POST" action="control.jsp">
+			<input type="hidden" name="device" value="DOSING_PUMP"/>
+			<input type="submit" value="Stop/Start"/>
+		</form></td>
+	</tr>
+	<tr>
+		<th>SIGNATURE</th>
+		<% if (signatureDeviceManager == null) { %>
+		<td>NO DRIVER LOADED</td>
+		<td>false</td>
+		<% } else { %>
+		<td><%= signatureDeviceManager.getClassName() %></td>
+		<td><%= signatureDeviceManager.getActive() %></td>
+		<% } %>
+		<td><form method="POST" action="control.jsp">
+			<input type="hidden" name="device" value="SIGNATURE"/>
+			<input type="submit" value="Stop/Start"/>
+		</form></td>
+	</tr>
+	<tr>
+		<th>LABEL</th>
+		<% if (labelPrinterDeviceManager == null) { %>
+		<td>NO DRIVER LOADED</td>
+		<td>false</td>
+		<% } else { %>
+		<td><%= labelPrinterDeviceManager.getClassName() %></td>
+		<td><%= labelPrinterDeviceManager.getActive() %></td>
+		<% } %>
+		<td><form method="POST" action="control.jsp">
+			<input type="hidden" name="device" value="LABEL"/>
+			<input type="submit" value="Stop/Start"/>
+		</form></td>
+	</tr>
+</table>
+
+</body>
+</html>
diff --git a/shim-webapp/src/main/webapp/img/freeshim.png b/shim-webapp/src/main/webapp/img/freeshim.png
new file mode 100644
index 0000000..7b9d8c0
Binary files /dev/null and b/shim-webapp/src/main/webapp/img/freeshim.png differ
diff --git a/shim-webapp/src/main/webapp/index.jsp b/shim-webapp/src/main/webapp/index.jsp
new file mode 100644
index 0000000..6db0406
--- /dev/null
+++ b/shim-webapp/src/main/webapp/index.jsp
@@ -0,0 +1,43 @@
+<%-- 
+ * $Id: index.jsp 394 2010-04-23 15:12:34Z jeff $
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management System
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ --%>
+<html>
+<head>
+<title>FreeSHIM</title>
+</head>
+<body>
+
+<!-- Header -->
+
+<table border="0" cellpadding="5" width="100%">
+	<tr>
+		<td align="right"><img src="img/freeshim.png" border="0" alt="" width="200" height="98" /></td>
+		<td align="left">FreeSHIM</td>
+	</tr>
+</table>
+
+This is the web administration interface for <em>FreeSHIM</em>. Web services
+are located <a href="services/">here</a>.
+
+</body>
+</html>
diff --git a/shim-webapp/test/soap-client.php b/shim-webapp/test/soap-client.php
new file mode 100755
index 0000000..4c37c51
--- /dev/null
+++ b/shim-webapp/test/soap-client.php
@@ -0,0 +1,78 @@
+#!/usr/bin/env php
+<?php
+/*
+ * $Id$
+ *
+ * Authors:
+ *      Jeff Buchbinder <jeff at freemedsoftware.org>
+ *
+ * FreeMED Electronic Medical Record / Practice Management
+ * Copyright (C) 1999-2012 FreeMED Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Suite 500, Boston, MA 02110, USA.
+ */
+
+$protocol = "http";
+$url = "localhost:8080/shim";
+$username = 'Administrator';
+$password = 'password';
+
+print '$Id$' . "\n";
+print "SOAP Testing interface for shim\n";
+print "\n";
+
+// Hack to deal with Basic Authentication protected WSDL
+$temp = tempnam( "/tmp", "wsdl");
+print " * Fetching WSDL from $url using $protocol (username $username) ... ";
+file_put_contents( $temp, file_get_contents($protocol."://".urlencode($username).":".urlencode($password)."@".$url."/services/ShimService?wsdl") );
+print "done.\n\n";
+
+$sc = new SoapClient( $temp, array(
+	  'login' => $username
+	, 'password' => $password
+	, 'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP
+));
+
+print "getProtocolVersion : \n";
+print_r( $sc->getProtocolVersion() );
+print "\n";
+
+print "requestSignature('Patient: Me') : \n";
+$id = $sc->requestSignature((object)array("displayInformation" => "Patient: " . ( $argv[1] != '' ? $argv[1] : "Me" ) ))->return;
+print_r( $id );
+print "\n";
+
+$x = (object) array( 'return' => '' );
+
+while ($x->return != 'COMPLETE' && $x->return != 'ERROR') {
+	print "getJobStatus ( $id ) : \n";
+	$x = $sc->getJobStatus((object)array("requestId" => $id));
+	print_r( $x );
+	print "\n";
+	if ($x->return != 'COMPLETE' && $x->return != 'ERROR') {
+		// Only wait if we're not done yet.
+		sleep (5);
+	}
+}
+
+print "getJobItem ( $id ) : \n";
+$x = $sc->getJobItem((object)array("requestId" => $id));
+print_r( $x );
+file_put_contents( "/tmp/test.png", $x->return->signatureImage );
+print "\n";
+
+unlink($temp);
+
+?>

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/freeshim.git



More information about the debian-med-commit mailing list